
/**
 * 这个窗体在负责主页面上的所有弹出窗口,因此它必须接受外面的参数来配置自己,以适应不同的需要,主要有以下几点: 窗口的形态:标题,宽高
 */
Hxcy.Window = function(config) {
	config = config || {};
	config.elements = 'tbar, body';
	Hxcy.Window.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.Window, Ext.Window, {
			/**
			 * @cfg {Array} tbarItems 主要用来配置窗口中可以切换的工具栏
			 */

			// popLink : [],
			afterRender : function(ct, position) {
				Hxcy.Window.superclass.afterRender.call(this, ct, position);
				this.tbarCt = this.getEl().child("div.x-window-tbar");
				var ti = this.tbarItems || [];
				this.tbarItems = new Ext.util.MixedCollection(false, function(o) {
							return o.itemId || o.id || Ext.id();
						});
				for (var index = 0, len = ti.length; index < len; index++) {
					this.tbarItems.add(new Ext.Toolbar(ti[index])).render(this.tbarCt).hide();
				}
				this.on('show', this.changeTbar);
				this.tbarCt.addClass('x-hide-display');
			},
			add : function(comp) {
				Hxcy.Window.superclass.add.call(this, comp);
				if (comp.menuCfg && typeof comp.menuCfg == "object") {// 添加工具栏
					if (this.rendered) {
						if (!this.tbarItems.key(comp.menuCfg.id)) {
							this.tbarItems.add(new Ext.Toolbar(comp.menuCfg)).render(this.tbarCt).hide();
						} else {// 这是一个比较特别的情况：就是面板现在用的工具栏已经被其它组件用过了
							this.tbarItems.key(comp.menuCfg.id).show();
							this.tbarCt.removeClass('x-hide-display');
						}
					} else {
						this.tbarItems = this.tbarItems || []
						this.tbarItems.push(comp.menuCfg);
					}
				}
			},

			changeTbar : function() {
				var t = this.layout ? this.layout.activeItem : null;
				this.tbarItems.each(function(items) {
					items.hide();
				});
				this.tbarCt.addClass('x-hide-display');
				if (t && t.menuCfg && this.tbarItems.key(t.menuCfg.id)) {
					this.tbarItems.key(t.menuCfg.id).show();
					this.tbarCt.removeClass('x-hide-display');
				}
			},
			hide : function(){
				this.restore();
				Hxcy.Window.superclass.hide.call(this);
			},
			afterHide : function() {
				Hxcy.Window.superclass.afterHide.call(this);
				if (this.popLink && this.popLink.length > 0) {
					this.popWindow(this.popLink.pop());
				}
			},
			popWindow : function(component) {
				if (component) {
					if (!this.findById(Ext.id(component))) {
						this.add(Ext.ComponentMgr.create(component, 'panel'));
					}
					// 这里有两个this.isVisible()调用主要是为了解决在此弹出窗口中又用此弹出窗口弹出其它内容
					this.isVisible() ? (this.popLink = (this.popLink || [])).push(this.layout.activeItem) : "";
					// 这里一定要小心，先设置活动面板，再显示窗体的方法是怎样的
					this.rendered ? this.getLayout().setActiveItem(component.id) : this.activeItem = component.id;
					component.winCfg ? this.setSize(component.winCfg.width || 600, component.winCfg.height || 400) : this.setSize(600, 400);
					if (this.isVisible()) {
						this.doLayout();
						this.fireEvent("show");// 当窗口是可见的时候需要手动触发show事件以便切换工具栏
					} else {
						this.show();
					}
					component.winCfg ? this.setTitle(component.winCfg.title || this.title, component.winCfg.iconCls || this.iconCls) : this.setTitle("弹出窗口", "x-accordion-item");
					this.buttons[0].setText('提交');
					this.buttons[1].setText('关闭');
					if (component.winCfg) {
						component.winCfg.btn0 === false ? this.buttons[0].hide() : this.buttons[0].show();
						component.winCfg.btn1 === false ? this.buttons[1].hide() : this.buttons[1].show();
						component.winCfg.btn0Text ? this.buttons[0].setText(component.winCfg.btn0Text):"";
						component.winCfg.btn1Text ? this.buttons[1].setText(component.winCfg.btn1Text):"";
						this.buttons[0].handler = component.winCfg.btn0Handler ? component.winCfg.btn0Handler : this.defaultSubmit;
						this.buttons[1].handler = component.winCfg.btn1Handler ? component.winCfg.btn1Handler : this.defaultClose.createDelegate(this,[component.winCfg]);
					}
					this.center();
				} else {
					alert('无显示内容');
				}
				return this;
			}
		});

Ext.reg('hxcywindow',Hxcy.Window);

/*Hxcy.TabPanel = function(config) {
	config = config || {};
	config.elements = 'tbar, body';
	Hxcy.TabPanel.superclass.constructor.call(this, config);
	this.on("beforetabchange", function(tp, np, cp) {
				if (cp && cp.menuCfg && this.tbarItems.key(cp.menuCfg.id)) {
					this.tbarItems.key(cp.menuCfg.id).hide()
				}
				if (np && np.menuCfg && this.tbarItems.key(np.menuCfg.id)) {
					this.tbarItems.key(np.menuCfg.id).show();
					this.tbarCt.removeClass('x-hide-display');
				} else {
					this.tbarCt.addClass('x-hide-display');
				}
				return true;
			});
};

Ext.extend(Hxcy.TabPanel, Ext.TabPanel, {
			*//**
			 * @cfg {Array} tbarItems 主要用来配置标签面板中可以切换的工具栏
			 *//*

			*//**
			 * @cfg {String} closeAction
			 *      主要用来配置标签的关闭行为，可以取close与hide两个值，如果取hide则表示只隐藏标签不销毁DOM
			 *//*
//			closeAction : 'hide',

			*//**
			 * @cfg {String} tbarCt 工具栏的容器
			 *//*

			afterRender : function(ct, position) {
				Hxcy.TabPanel.superclass.afterRender.call(this, ct, position);
				this.tbarCt = this.getEl().child("div.x-tab-panel-tbar");
				var ti = this.tbarItems || [];
				this.tbarItems = new Ext.util.MixedCollection(false, function(o) {
							return o.itemId || o.id || Ext.id();
						});
				for (var index = 0, len = ti.length; index < len; index++) {
					this.tbarItems.add(new Ext.Toolbar(ti[index])).render(this.tbarCt).hide();
				}
				this.tbarCt.addClass('x-hide-display');
			},

			onBeforeAdd : function(item) {
				Hxcy.TabPanel.superclass.onBeforeAdd.call(this, item);
				if (item.menuCfg && typeof item.menuCfg == "object") {// 添加工具栏
					if (this.rendered) {
						if (!this.tbarItems.key(item.menuCfg.id)) {
							this.tbarItems.add(new Ext.Toolbar(item.menuCfg)).render(this.tbarCt).hide()
						} else {// 这种情况是：当前面板指定的工具栏是已经被其它面板注册到此tabpanel中了
							this.tbarItems.key(item.menuCfg.id).show();
							this.tbarCt.removeClass('x-hide-display');
						}
					} else {
						this.tbarItems = this.tbarItems || []
						this.tbarItems.push(item.menuCfg);
					}
				}
			},

			showTab : function(component) {
				if (component) {
					if (!this.findById(component.id)) {
						var t = this.add(component);
					}
					this.setActiveTab(t || component.id);
				} else {
					alert('无显示内容');
				}
			}

		});

Ext.reg('hxcytabpanel', Hxcy.TabPanel);*/

Hxcy.TabPanel = Ext.extend(Ext.TabPanel, {
	//closeAction : 'hide',
	showTab : function(itemCfg) {
		if (itemCfg) {
			if (!this.findById(itemCfg.id)) {
				var t = this.add(itemCfg);
			}
			this.setActiveTab(t || itemCfg.id);
		} else {
			alert('无显示内容');
		}
	}
});
Ext.reg('hxcytabpanel', Hxcy.TabPanel);

//下面的处理有些不好,它的限定只针对全局唯一的Hxcy.TabPanel实例,并且它的id是固定的
Hxcy.showTab = function(itemCfg){
	Hxcy.TabPanel = Hxcy.TabPanel || Ext.getCmp('contentWrapper')||top.Ext.getCmp('contentWrapper');
	Hxcy.TabPanel.showTab(itemCfg);
};

Hxcy.MasterSlavePanel = function(config) {
	config.layout = 'border';
	config.sconfig = config.sconfig || {};
	var master = config.master;
	var slave = config.slave;
	if(!config.direction||config.direction=='ud'||config.direction=='up-down'){
		master.region = 'center';
		slave.region = 'south';
		slave.height = config.sconfig.size || 200;
	} else if(config.direction=='lr'||config.direction=='left-right'){
		master.region = 'center';
		slave.region = 'east';
		slave.width = config.sconfig.size || 600;
	} else {
		alert('指定的方向不正确');
	}
	Hxcy.Util.applyIf(master, config.mconfig);
	Hxcy.Util.applyIf(slave, config.sconfig);
	config.items = [master, slave];
	Hxcy.MasterSlavePanel.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.MasterSlavePanel, Ext.Panel, {
	initEvents : function(){
		Hxcy.MasterSlavePanel.superclass.initEvents.call(this);
		var master = this.items.itemAt(0);
		var slave = this.items.itemAt(1);
		master.relayEvents(this, ['show']);
		master.selModel.addListener('rowselect', this.onMasterSelect, this);
		master.selModel.addListener('rowdeselect', this.onMasterDeselect, this);
		//主要用监听主表加载后,从表需要置空的操作
		master.store.addListener('load', this.onMasterDeselect, this);
	},
	onMasterSelect : function(masterSM, rowIndex, rd){
		var slave = this.items.itemAt(1);
		slave.getEl().unmask();
		var params = {};
		params['page.start']=slave['page.start']||0;
		params['page.limit']=slave['page.limit']||20;
		var baseParams = {};
		for(var p in slave.masterParams){
			baseParams[p]=rd.get(slave.masterParams[p]);
		}
		Ext.apply(slave.store.baseParams, baseParams||{});
		slave.store.load({params : params});
		if (typeof slave.maskCallback=='function'&&slave.maskCallback(this.items.itemAt(0))) {
			slave.getEl().mask();//需要锁定从表
		}
	},
	onMasterDeselect : function(masterSM, rowIndex, rd){
		var slave = this.items.itemAt(1);
		for(var p in slave.masterParams){
			delete slave.store.baseParams[p];
		}
		if (slave.deselectStrategy=='reload') {
			var params = {};
			params['page.start']=slave['page.start']||0;
			params['page.limit']=slave['page.limit']||10;
			slave.store.load({params : params});
			if (typeof slave.maskCallback=='function'&&slave.maskCallback(this.items.itemAt(0))) {
				slave.getEl().mask();//需要锁定从表
			}
		} else if(!slave.deselectStrategy||slave.deselectStrategy=='clear'){
			slave.getEl().mask();//如果清除记录则将从表锁定
			slave.store.removeAll();
			slave.store.totalLength=0;
			var bar = slave.getTopToolbar();
			if (bar.pageSize) {
				bar.onLoad(slave.store, null, {});
			}
			bar = slave.getBottomToolbar();
			if (bar.pageSize) {
				bar.onLoad(slave.store, null, {});
			}
		}
	}
});

Ext.reg('mspanel', Hxcy.MasterSlavePanel);

Hxcy.IFrame = Ext.extend(Ext.BoxComponent, {
	onRender : function(ct, position) {
		this.el = ct.createChild({
			tag : 'iframe',
			id : this.id + '-iframe',
			name : this.id + '-iframe',
			frameBorder : 0,
			src : this.url
		});
	}
});

Ext.reg('iframe', Hxcy.IFrame);


Hxcy.Button = Ext.extend(Ext.Button, {
	onRender : function(ct, position) {
		if (!this.template) {
			if (!Hxcy.Button.buttonTemplate) {
				Hxcy.Button.buttonTemplate = new Ext.Template('<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
						'<td class="x-btn-left"><i>&#160;</i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}"></button>{0}</em></td><td class="x-btn-right"><i>&#160;</i></td>', "</tr></tbody></table>");
			}
			this.template = Hxcy.Button.buttonTemplate;
		}
		var btn, targs = [this.text || '&#160;', this.type];

		if (position) {
			btn = this.template.insertBefore(position, targs, true);
		} else {
			btn = this.template.append(ct, targs, true);
		}
		var btnEl = btn.child(this.buttonSelector);
		btnEl.on('focus', this.onFocus, this);
		btnEl.on('blur', this.onBlur, this);

		this.initButtonEl(btn, btnEl);

		if (this.menu) {
			this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
		}
		Ext.ButtonToggleMgr.register(this);
	}
});

Ext.reg('hxcybutton', Hxcy.Button);

Hxcy.BoxButton = Ext.extend(Ext.Button, {
	initComponent : function(){
		Ext.BoxComponent.superclass.initComponent.call(this);
		if (!Hxcy.BoxButton.buttonTemplate) {
			Hxcy.BoxButton.buttonTemplate = new Ext.Template(
			'<table border="0" cellpadding="0" cellspacing="0" class="x-btn {3}"><tbody class="{4}"><tr>',
			'<td class="x-btn-left"><i>&#160;</i></td>',
			'<td class="x-btn-center"><em unselectable="on"><button class="x-btn-text {2}" type="{1}">&#160</button>{0}</em></td>',
			'<td class="x-btn-right"><i>&#160;</i></td>', "</tr></tbody></table>");
			Hxcy.BoxButton.buttonTemplate.compile();
		}
		this.template = Hxcy.BoxButton.buttonTemplate;
		this.addEvents('click');//增加的click事件
	},
	onClick : function(e){
        if(e){
            e.preventDefault();
        }
        if(e.button !== 0){
            return;
        }
        if(!this.disabled){
            if(this.enableToggle && (this.allowDepress !== false || !this.pressed)){
                this.toggle();
            }
            if(this.menu && !this.menu.isVisible() && !this.ignoreNextClick){
                this.showMenu();
            }
            this.fireEvent('click', this, e);
            if(this.handler){
                //this.el.removeClass('x-btn-over');
                this.handler.call(this.scope || this, this, e);
            }
        }
    }
});
Ext.reg('Hxcyboxbutton', Hxcy.BoxButton);

Hxcy.Cmp = {};
Hxcy.Cmp.Cfg = function(zIndex) {
	var id = 'hxcy-menu-pop-window-' + zIndex;
	var defaultSubmit = function() {
		Ext.ComponentMgr.get(id).layout.activeItem.getForm().submit({
			//clientValidation : false,
			waitMsg : "正在处理..."
		});
	};
	var defaultClose = function(winCfg) {
		if (winCfg.closeBefore && winCfg.closeBefore()===false) {
			return ;
		}
		Ext.ComponentMgr.get(id).hide();
		if (winCfg.closeAfter) {
			winCfg.closeAfter();
		}
	};
	return {
		popWndCfg : {
			id : id,
			xtype : 'hxcywindow',
			width : 600,
			height : 400,
			title : '样本窗体',
			iconCls : "x-accordion-item ",
			// minimizable : true,
			collapsible : true,
			maximizable : true,
			constrain : true,
			resizable : true,
			autoScroll : true,
			modal : true,
			closeAction : "hide",
			layout : "card",
			activeItem : 0,
			defaultSubmit : defaultSubmit,
			defaultClose : defaultClose,
			buttons : [{
						id : "pop-wnd-submit-" + zIndex,
						text : "提交",
						handler : defaultSubmit
					}, {
						id : "pop-wnd-close-" + zIndex,
						text : "关闭",
						handler : defaultClose
					}]
		}
	};
}

Hxcy.CmpMgr = function() {
	var popWnds = new Ext.util.MixedCollection(false, function(o) {
				return o.itemId || o.id || Ext.id();
			});

	var tabPanel = null;
	var id = 'hxcy-menu-pop-window-';
	var wndBtnCtx =[];
	return {
		popWindow : function(component) {
			var popWnd = null;
			if (component) {
				if (component.winCfg && component.winCfg.zIndex) {
					popWnd = popWnds.key(id + component.winCfg.zIndex) || popWnds.add(Ext.ComponentMgr.create(Hxcy.Cmp.Cfg(component.winCfg.zIndex).popWndCfg));
				} else {
					popWnd = popWnds.key(id + '0') || popWnds.add(Ext.ComponentMgr.create(Hxcy.Cmp.Cfg('0').popWndCfg));
				}
			} else {
				alert('无显示内容');
				return;
			}
			var window = popWnd.popWindow(component);
			if(wndBtnCtx.length>0){//此处主要是为让其它组件注册此窗体的按钮
				var ctx=null;
				while(ctx=wndBtnCtx.pop()){
					for (var index = 0; index < popWnd.buttons.length; index++) {
						popWnd.buttons[index][ctx.ctxName]=ctx;
					}
				}
			}
			return window;
		},

		showTab : function(component) {
			tabPanel = tabPanel || Ext.getCmp('contentWrapper')||top.Ext.getCmp('contentWrapper');
			tabPanel.showTab(component);
		},
		
		registerBtnCtx : function(ctx){
			wndBtnCtx.push(ctx);
		},
		
		hideWindow : function(index){
			popWnds.itemAt(index||0).hide();
		}
	}
}();

Ext.form.FileUploadField = Ext.extend(Ext.form.TextField, {
	/**
	 * @cfg {String} buttonText The button text to display on the upload
	 *      button (defaults to 'Browse...'). Note that if you supply a
	 *      value for {@link #buttonCfg}, the buttonCfg.text value will
	 *      be used instead if available.
	 */
	buttonText : '浏览...',
	/**
	 * @cfg {Boolean} buttonOnly True to display the file upload field
	 *      as a button with no visible text field (defaults to false).
	 *      If true, all inherited TextField members will still be
	 *      available.
	 */
	buttonOnly : false,
	/**
	 * @cfg {Number} buttonOffset The number of pixels of space reserved
	 *      between the button and the text field (defaults to 3). Note
	 *      that this only applies if {@link #buttonOnly} = false.
	 */
	buttonOffset : 3,
	/**
	 * @cfg {Object} buttonCfg A standard {@link Ext.Button} config
	 *      object.
	 */

	// private
	readOnly : true,

	/**
	 * @hide
	 * @method autoSize
	 */
	autoSize : Ext.emptyFn,

	// private
	initComponent : function() {
		Ext.form.FileUploadField.superclass.initComponent.call(this);

		this.addEvents(
				/**
				 * @event fileselected Fires when the underlying file
				 *        input field's value has changed from the user
				 *        selecting a new file from the system file
				 *        selection dialog.
				 * @param {Ext.form.FileUploadField}
				 *            this
				 * @param {String}
				 *            value The file value returned by the
				 *            underlying file input field
				 */
				'fileselected');
	},

	// private
	onRender : function(ct, position) {
		Ext.form.FileUploadField.superclass.onRender.call(this, ct, position);

		this.wrap = this.el.wrap({
			cls : 'x-form-field-wrap x-form-file-wrap'
		});
		this.el.addClass('x-form-file-text');
		this.el.dom.removeAttribute('name');

		this.fileInput = this.wrap.createChild({
			id : this.getFileInputId(),
			name : this.name || this.getId(),
			cls : 'x-form-file',
			tag : 'input',
			type : 'file',
			size : 1
		});

		var btnCfg = Ext.applyIf(this.buttonCfg || {}, {
					text : this.buttonText
				});
		this.button = new Ext.Button(Ext.apply(btnCfg, {
					renderTo : this.wrap,
					cls : 'x-form-file-btn' + (btnCfg.iconCls ? ' x-btn-icon' : '')
				}));

		if (this.buttonOnly) {
			this.el.hide();
			this.wrap.setWidth(this.button.getEl().getWidth());
		}

		this.fileInput.on('change', function() {
					var v = this.fileInput.dom.value;
					this.setValue(v);
					this.fireEvent('fileselected', this, v);
				}, this);
	},

	// private
	getFileInputId : function() {
		return this.id + '-file';
	},

	// private
	onResize : function(w, h) {
		Ext.form.FileUploadField.superclass.onResize.call(this, w, h);

		this.wrap.setWidth(w);

		if (!this.buttonOnly) {
			var w = this.wrap.getWidth() - this.button.getEl().getWidth() - this.buttonOffset;
			this.el.setWidth(w);
		}
	},

	// private
	preFocus : Ext.emptyFn,

	// private
	getResizeEl : function() {
		return this.wrap;
	},

	// private
	getPositionEl : function() {
		return this.wrap;
	},

	// private
	alignErrorIcon : function() {
		this.errorIcon.alignTo(this.wrap, 'tl-tr', [2, 0]);
	}

});
Ext.reg('fileuploadfield', Ext.form.FileUploadField);

Ext.form.Image = Ext.extend(Ext.BoxComponent, {
	initComponent : function() {
		Ext.form.Image.superclass.initComponent.call(this);
		this.addEvents('click');

	},
	onRender : function(ct, position) {
		if (!this.el) {
			this.el = document.createElement('img');
			this.el.src = this.src;
			if (this.forId) {
				this.el.setAttribute('htmlFor', this.forId);
			}
		}

		Ext.form.Label.superclass.onRender.call(this, ct, position);
	},
	afterRender : function() {
		Ext.form.Image.superclass.afterRender.call(this);		
		 this.el.on("click", this.onClick, this);
	},
	onClick : function() {
		if (this.handler === true)
			this.el.dom.src = this.src + '?date=' + new Date();
		else if (Ext.type(this.handler) == 'function')
			this.handler(this);
		this.fireEvent("click", this);
	}

});
Ext.reg('image', Ext.form.Image);

Hxcy.CrudTbar = function(config) {
	config = config || {};
	config.linkId = config.linkId || 'linkId';
	config.id = config.linkId + '-crud-tbar';
	Hxcy.CrudTbar.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.CrudTbar, Ext.Toolbar, {
	initComponent : function() {
		Hxcy.CrudTbar.superclass.initComponent.call(this);
		var linkId = this.linkId;
		var id = this.id;
		var handlers = this.handlers || {};
		var urls = this.urls || {};
		var saveArg = this.saveArg;
		var deleteArg = this.deleteArg;
		this.crudButtons = [{
					id : id + '-add',
					group : 'one',
					text : '添加',
					handler : handlers.addHandler,
					listeners : {
						click : function() {
							var fp = Ext.getCmp(linkId + "-grid-link-form");
							if (fp) {
								fp.items.each(function(item) {
									item.enable();
								});
								fp.getForm().reset();
								var t = fp.getForm().findField('crudType');
								t ? t.setValue('save') : "";
								fp.getForm().lock = true;
							}
							var tbar = Ext.getCmp(id);
							tbar.items.each(function(item) {
								item.group == 'two' ? item.enable() : item.disable();
							});
						}
					}
				}, {
					id : id + '-update',
					group : 'one',
					text : '修改',
					handler : handlers.updateHandler,
					listeners : {
						click : function() {
							var fp = Ext.getCmp(linkId + "-grid-link-form");
							if (fp) {
								fp.items.each(function(item) {
									item.enable();
								});
								var t = fp.getForm().findField('crudType');
								t ? t.setValue('update') : "";
								fp.getForm().lock = true;
							}
							var tbar = Ext.getCmp(id);
							tbar.items.each(function(item) {
								item.group == 'two' ? item.enable() : item.disable();
							});
						}
					}
				}, {
					id : id + '-delete',
					group : 'one',
					text : '删除',
					handler : function() {
						var fp = Ext.getCmp(linkId + '-grid-link-form');
						var form = fp.getForm();
						var crudType = form.findField('crudType').getValue();
						if (handlers.removeBeforeHandler) {
							if (handlers.removeBeforeHandler(fp, crudType)===false) {
								return ;
							}
						}
						fp.items.each(function(item) {
							item.enable();
						});
						Ext.Msg.confirm('确认', "<br />确定要删除所选项吗?", function(btn) {
									if (btn == "yes") {// 确认提交
										if (crudType == 'remove') {
											form.submit({
												url : urls.removeUrl || "#",
												waitMsg : "正在处理...",
												success : function(){
													if (handlers.removeAfterHandler) {
														handlers.removeAfterHandler(fp, crudType);
													}
												}
											});
										}
									} else if (btn == 'no') {
										fp.items.each(function(item) {
											item.disable();
										});
									}
								});
					},
					listeners : {
						click : function() {
							var fp = Ext.getCmp(linkId + "-grid-link-form");
							if (fp) {
								var t = fp.getForm().findField('crudType');
								t ? t.setValue('remove') : "";
							}
						}
					}
				}, '-', {
					id : id + '-save',
					group : 'two',
					text : '保存',
					handler : function() {
						var fp = Ext.getCmp(linkId + '-grid-link-form');
						var form = fp.getForm();
						var crudType = form.findField('crudType').getValue();
						if (handlers.saveBeforeHandler) {
							handlers.saveBeforeHandler(fp, crudType);
						}
						if (crudType == 'save') {
							form.submit({
								url : urls.saveUrl || "#",
								waitMsg : "正在处理...", 
								success : function(){
									if (handlers.saveAfterHandler) {
										handlers.saveAfterHandler(fp, crudType);
									}
								}
							});
						} else if (crudType == 'update') {
							form.submit({
								url : urls.updateUrl || "#",
								waitMsg : "正在处理...",
								success : function(){
									if (handlers.saveAfterHandler) {
										handlers.saveAfterHandler(fp, crudType);
									}
								}
							});
						}
					},
					disabled : true
				}, {
					id : id + '-cancel',
					group : 'two',
					text : '放弃',
					handler : handlers.cancelHandler,
					disabled : true,
					listeners : {
						click : function() {
							var fp = Ext.getCmp(linkId + "-grid-link-form");
							var gd = Ext.getCmp(linkId + '-form-link-grid');
							var rd = gd ? gd.selModel.getSelected() : null;
							if (fp) {
								fp.items.each(function(item) {
									item.disable();
								});
								fp.getForm().lock = false;
								rd ? fp.getForm().loadRecord(rd) : "";
							}
							var tbar = Ext.getCmp(id);
							tbar.items.each(function(item) {
								item.group == 'one' ? item.enable() : item.disable();
							});
						}
					}
				}];
	},
	afterRender : function() {
		Hxcy.CrudTbar.superclass.afterRender.call(this);
		if (this.crudButtons) {
			this.add.apply(this, this.crudButtons);
			delete this.crudButtons;
		}
	}
});

Ext.reg('crudtbar', Hxcy.CrudTbar);

Hxcy.LinkGrid = function(config) {
	config = config || {};
	config.linkId = config.linkId || 'linkId';
	config.id = config.linkId + '-form-link-grid';
	Hxcy.Util.applyIf(config, {
		region : 'center',
		xtype : 'grid',
		closable : true,
		border : false,
		frame : false,
		viewConfig : {
			forceFit : true
		}
	});
	Ext.applyIf(config, {
		bbar : new Ext.PagingToolbar({
			pageSize : config.pageSize || 10,
			store : config.store,
			paramNames : {
				start : 'page.start',
				limit : 'page.limit'
			},
			displayInfo : true,
			displayMsg : '第{0}条 - 第{1}条 共{2}条',
			emptyMsg : "没有可显示的记录"
		})
	});
	Hxcy.LinkGrid.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.LinkGrid, Ext.grid.GridPanel, {

		});

Ext.reg('linkgrid', Hxcy.LinkGrid);

Hxcy.LinkForm = function(config) {
	config = config || {};
	config.linkId = config.linkId || 'linkId';
	config.id = config.linkId + '-grid-link-form';
	config.hasB = config.hasB === undefined;
	config.hasT = !config.hasB;
	Hxcy.Util.applyIf(config, {
		xtype : 'form',
		defaultType : 'textfield',
		layoutConfig : {// 专有布局配置
			labelWidth : 75,
			labelPad : 20,// 标签内边距
			labelAlign : "left",
			labelSeparator : '：'
		},
		defaults : {// 应用于所有子组件的公共配置
			width : 240,
			anchor : '90%',
			validateOnBlur : false,// 这里阻止客户端检验的表象效果发生,而最终是否校验决定于最后提交时的选项
			validationEvent : false,
			disabled : true,
			msgTarget : 'side'
		},
		border : false,
		bodyStyle : 'padding:10px;',
		region : 'east',
		height : 200,
		width : 380,
		split : true,
		collapseMode : "mini"
	});
	Ext.applyIf(config, {
		bbar : config.hasB ? new Hxcy.CrudTbar({
			linkId : config.linkId,
			saveArg : config.saveArg,
			deleteArg : config.deleteArg,
			handlers : config.handlers,
			urls : config.urls
		}) : undefined,
		tbar : config.hasT ? new Hxcy.CrudTbar({
			linkId : config.linkId,
			saveArg : config.saveArg,
			deleteArg : config.deleteArg,
			handlers : config.handlers,
			urls : config.urls
		}) : undefined
	});
	Hxcy.LinkForm.superclass.constructor.call(this, config);
};

Ext.app.App = function(cfg){
    Ext.apply(this, cfg);
    this.addEvents({
        'ready' : true,
        'beforeunload' : true
    });

    Ext.onReady(this.initApp, this);
};

Ext.extend(Ext.app.App, Ext.util.Observable, {
    isReady: false,
    startMenu: null,
    modules: null,

    getStartConfig : function(){

    },

    initApp : function(){
    	this.startConfig = this.startConfig || this.getStartConfig();

        this.desktop = new Ext.Desktop(this);

		this.launcher = this.desktop.taskbar.startMenu;

		this.modules = this.getModules();
        if(this.modules){
            this.initModules(this.modules);
        }

        this.init();

        Ext.EventManager.on(window, 'beforeunload', this.onUnload, this);
		this.fireEvent('ready', this);
        this.isReady = true;
    },

    getModules : Ext.emptyFn,
    init : Ext.emptyFn,

    initModules : function(ms){
		for(var i = 0, len = ms.length; i < len; i++){
            var m = ms[i];
            this.launcher.add(m.launcher);
            m.app = this;
        }
    },

    getModule : function(name){
    	var ms = this.modules;
    	for(var i = 0, len = ms.length; i < len; i++){
    		if(ms[i].id == name || ms[i].appType == name){
    			return ms[i];
			}
        }
        return '';
    },

    onReady : function(fn, scope){
        if(!this.isReady){
            this.on('ready', fn, scope);
        }else{
            fn.call(scope, this);
        }
    },

    getDesktop : function(){
        return this.desktop;
    },

    onUnload : function(e){
        if(this.fireEvent('beforeunload', this) === false){
            e.stopEvent();
        }
    }
});

Ext.app.Module = function(config){
    Ext.apply(this, config);
    Ext.app.Module.superclass.constructor.call(this);
    this.init();
}

Ext.extend(Ext.app.Module, Ext.util.Observable, {
    init : Ext.emptyFn
});



Ext.app.SearchField = Ext.extend(Ext.form.TwinTriggerField, {
	initComponent : function() {
		Ext.app.SearchField.superclass.initComponent.call(this);
		this.on('specialkey', function(f, e) {
					if (e.getKey() == e.ENTER) {
						this.onTrigger2Click();
					}
				}, this);
		this.otherFields = this.otherFields || [];
		if (!Ext.isArray(this.otherFields)) {
			this.otherFields = [this.otherFields];
		}
		this.selfField ? this.otherFields.push(this.id) : "";
	},

	validationEvent : false,
	validateOnBlur : false,
	trigger1Class : 'x-form-clear-trigger',
	trigger2Class : 'x-form-search-trigger',
	hideTrigger1 : true,
	width : 180,
	selfField : true,
	paramNames : {
		start : 'page.start'
	},

	prepareData : function() {
		this.store.baseParams = this.store.baseParams || {};
		Ext.each(this.otherFields, function(item) {
					var field = Ext.getCmp(item);
					//这里不要使用field.getValue或field.getRawValue,如果使用field.getValue,则获取的值是一个有类型值可能与设定的格式不符合,例如日期;
					//如果是getRawValue可能获取并不是我们需要的值,例如下拉列表获取的是看得见的标签的值；但这里又出现一个问题像文本域非触发形的字段域，此值却为空
					this.store.baseParams[field.getName()] = field.value||field.getRawValue();
				}, this);

	},

	resetData : function() {
		this.store.baseParams = this.store.baseParams || {};
		Ext.each(this.otherFields, function(item) {
					var field = Ext.getCmp(item);
					field.reset();
					if (field.resetClear!==false) {//由字段配置来决定是否清除
						delete this.store.baseParams[field.getName()];
						delete this.store.lastOptions.params[field.getName()];
					} else {
						this.store.baseParams[field.getName()] = field.value||field.getRawValue();
					}
				}, this);
	},

	hasSearch : function() {
		return Ext.each(this.otherFields, function(item) {
					var field = Ext.getCmp(item);
					if (field.getRawValue()) {
						return false;
					};
				}, this) == undefined ? false : true;
	},

	onTrigger1Click : function() {
		if (this.hasSearch()) {
			this.el.dom.value = '';
			var o = {};
			this.store.lastOptions.params[this.paramNames.start] = 0;
			this.resetData();
			this.store.reload();
			this.triggers[0].hide();
		}
	},

	onTrigger2Click : function() {
		if (!this.hasSearch()) {
			this.onTrigger1Click();
			return;
		}
		var o = {};
		//以下这一行以前是注释的
		this.store.lastOptions = this.store.lastOptions || {params : {}};
		this.store.lastOptions.params = this.store.lastOptions.params || {};
		this.store.lastOptions.params[this.paramNames.start] = 0;
		this.prepareData();
		this.store.reload();
		this.triggers[0].show();
	}
});

Ext.reg('searchfield', Ext.app.SearchField);

Hxcy.SearchForm = Ext.extend(Ext.form.FormPanel, {
	initComponent :function(){
		Hxcy.SearchForm.superclass.initComponent.call(this);
		
	},
	submit : function(options){
		options = options || {};
		options.params = options.params||{};
		var formParams = this.getForm().getValues();
		
		if(this.bind===true){
			Ext.apply(this.store.baseParams, formParams);
		} else {
			Ext.applyIf(options.params, formParams);
		}
		Hxcy.Util.cfg(options, this.store.lastOptions);
		//写了转换器之后,这里就没必要
		/*
		for(var f in formParams){
			var v = this.getForm().findField(f).getValue();
			if(Ext.isEmpty(v)){//如果不空值则不向后台传值,因为由于转换器的原因传空值有可能变成false
				delete options.params[f];
			}
		}
		alert(Hxcy.Util.list(options.params));
		*/
		this.store.reload(options);
	},
	reset : function(options){
		options = options || {};
		options.params = options.params||{};
		this.getForm().reset();
		var formParams = this.getForm().getValues();
		if(this.bind===true){
			var formParams = this.getForm().getValues();
			for(var name in formParams){
				delete this.store.baseParams[name];
			}
		}
		Ext.applyIf(options.params, formParams);
		Hxcy.Util.cfg(options, this.store.lastOptions);
		for(var f in formParams){
			var v = this.getForm().findField(f).getValue();
			if(Ext.isEmpty(v)){//如果不空值则不向后台传值,因为由于转换器的原因传空值有可能变成false
				delete options.params[f];
			}
		}
		this.store.reload(options);
	}
});
Ext.reg('searchform', Hxcy.SearchForm);

Ext.extend(Hxcy.LinkForm, Ext.FormPanel, {
	afterRender : function() {
		Hxcy.LinkForm.superclass.afterRender.call(this);
		var fp = Ext.getCmp(this.linkId + '-grid-link-form');
		var form = fp.getForm();
		var tbar = Ext.getCmp(this.linkId + '-crud-tbar');
		var gd = Ext.getCmp(this.linkId + '-form-link-grid');
		form.on({
			'actioncomplete' : function(form, action) {
				var result = action.result;// 这是返回的结果对象
				var crudType = form.findField('crudType').getValue();
				var sm = gd.getSelectionModel();
				var store = gd.getStore();
				var currentRecord = sm.getSelected();// 当前网格中被选择的对象
				if (crudType == 'save') {
					store.reload();
					sm.selectFirstRow();
				} else if (crudType == 'update') {
					form.updateRecord(currentRecord);
					sm.selectNext();
					form.loadRecord(sm.getSelected());
				} else if (crudType == 'remove') {
					sm.selectNext();
					store.remove(currentRecord);
					form.reset();
					form.loadRecord(sm.getSelected() || {});
				}
				tbar.items.each(function(item) {
					item.group == 'one' ? item.enable() : item.disable();
				});
				form.lock = false;
				fp.items.each(function(item) {
					item.disable();
				});
			},
			'actionfailed' : function(form, action) {
				if (action.result&&action.result.actionErrors&&action.result.actionErrors.length>0) {
					Hxcy.Util.error(action.result.actionErrors);
				}
			},
			'beforeaction' : function(form, action) {
				// form.clearInvalid();
			}
		});

	}

});

Ext.reg('linkform', Hxcy.LinkForm);

Hxcy.FormGrid = function(config) {
	config = config || {};
	config.linkId = config.linkId || 'linkId-' + Ext.id();
	config.id = config.linkId + '-formGrid';

	config.linkGridCfg = config.linkGridCfg || {};
	config.linkFormCfg = config.linkFormCfg || {};
	Ext.applyIf(config.linkGridCfg, {
				linkId : config.linkId,
				xtype : 'linkgrid',
				pageSize : config.pageSize,
				store : config.store,
				cm : config.cm,
				sm : config.sm
			});
	Ext.applyIf(config.linkFormCfg, {
				linkId : config.linkId,
				xtype : 'linkform',
				hasB : config.hasB,
				region : config.region,
				saveArg : config.saveArg,
				deleteArg : config.deleteArg,
				handlers : config.handlers,
				urls : config.urls,
				items : config.fields
			});
	Hxcy.Util.applyIf(config, {
				layout : 'border',
				border : false,
				items : [config.linkGridCfg, config.linkFormCfg]
			});
	Hxcy.FormGrid.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.FormGrid, Ext.Panel, {

		});

Ext.reg('formgrid', Hxcy.FormGrid);

Ext.ns('Ext.ux.layout');
Ext.ux.layout.CenterLayout = Ext.extend(Ext.layout.FitLayout, {
			// private
			setItemSize : function(item, size) {
				this.container.addClass('ux-layout-center');
				item.addClass('ux-layout-center-item');
				if (item && size.height > 0) {
					if (item.width) {
						size.width = item.width;
					}
					item.setSize(size);
				}
			}
		});
Ext.Container.LAYOUTS['ux.center'] = Ext.ux.layout.CenterLayout;

Ext.ux.layout.RowLayout = Ext.extend(Ext.layout.ContainerLayout, {
	// private
	monitorResize : true,

	// private
	isValidParent : function(c, target) {
		return c.getEl().dom.parentNode == this.innerCt.dom;
	},

	// private
	onLayout : function(ct, target) {
		var rs = ct.items.items, len = rs.length, r, i;

		if (!this.innerCt) {
			target.addClass('ux-row-layout-ct');
			this.innerCt = target.createChild({
				cls : 'x-row-inner'
			});
		}
		this.renderAll(ct, this.innerCt);

		var size = target.getViewSize();

		if (size.width < 1 && size.height < 1) { // display none?
			return;
		}

		var h = size.height - target.getPadding('tb'), ph = h;

		this.innerCt.setSize({
			height : h
		});

		// some rows can be percentages while others are fixed
		// so we need to make 2 passes

		for (i = 0; i < len; i++) {
			r = rs[i];
			if (!r.rowHeight) {
				ph -= (r.getSize().height + r.getEl().getMargins('tb'));
			}
		}

		ph = ph < 0 ? 0 : ph;

		for (i = 0; i < len; i++) {
			r = rs[i];
			if (r.rowHeight) {
				r.setSize({
					height : Math.floor(r.rowHeight * ph) - r.getEl().getMargins('tb')
				});
			}
		}
	}

		/**
		 * @property activeItem
		 * @hide
		 */
	});
Ext.Container.LAYOUTS['ux.row'] = Ext.ux.layout.RowLayout;



/*
 * 2011-3-5 迁入
 */
Ext.ux.StartMenu = function(config){
	Ext.ux.StartMenu.superclass.constructor.call(this, config);
    
    var tools = this.toolItems;
    this.toolItems = new Ext.util.MixedCollection();
    if(tools){
        this.addTool.apply(this, tools);
    }
};

Ext.extend(Ext.ux.StartMenu, Ext.menu.Menu, {
    // private
    render : function(){
        if(this.el){
            return;
        }
        var el = this.el = new Ext.Layer({
            cls: "x-menu ux-start-menu", // this might affect item click
            shadow:this.shadow,
            constrain: false,
            parentEl: this.parentEl || document.body,
            zindex:15000
        });
        
        var header = el.createChild({
        	tag: "div",
        	cls: "x-window-header x-unselectable x-panel-icon "+this.iconCls
        });
		this.header = header;
		var headerText = header.createChild({
			tag: "span",
			cls: "x-window-header-text"
		});
		var tl = header.wrap({
			cls: "ux-start-menu-tl"
		});
		var tr = header.wrap({
			cls: "ux-start-menu-tr"
		});
		var tc = header.wrap({
			cls: "ux-start-menu-tc"
		});
		
		this.menuBWrap = el.createChild({
			tag: "div",
			cls: "x-window-body x-border-layout-ct ux-start-menu-body"
		});
		var ml = this.menuBWrap.wrap({
			cls: "ux-start-menu-ml"
		});
		var mc = this.menuBWrap.wrap({
			cls: "x-window-mc ux-start-menu-bwrap"
		});
		
		this.menuPanel = this.menuBWrap.createChild({
			tag: "div",
			cls: "x-panel x-border-panel ux-start-menu-apps-panel"
		});
		this.toolsPanel = this.menuBWrap.createChild({
			tag: "div",
			cls: "x-panel x-border-panel ux-start-menu-tools-panel"
		});
		
		var bwrap = ml.wrap({cls: "x-window-bwrap"});
		var bc = bwrap.createChild({
			tag: "div",
			cls: "ux-start-menu-bc"
		});
		var bl = bc.wrap({
			cls: "ux-start-menu-bl x-panel-nofooter"
		});
		var br = bc.wrap({
			cls: "ux-start-menu-br"
		});
		
        this.keyNav = new Ext.menu.MenuNav(this);

        if(this.plain){
            el.addClass("x-menu-plain");
        }
        if(this.cls){
            el.addClass(this.cls);
        }
        // generic focus element
        this.focusEl = el.createChild({
            tag: "a",
            cls: "x-menu-focus",
            href: "#",
            onclick: "return false;",
            tabIndex:"-1"
        });
        
        var ul = this.menuPanel.createChild({
        	tag: "ul",
        	cls: "x-menu-list"});
        var toolsUl = this.toolsPanel.createChild({
        	tag: "ul",
        	cls: "x-menu-list"
        });
        
        var ulListeners = {
        	"click": {
        		fn: this.onClick,
        		scope: this
        	},
        	"mouseover": {
        		fn: this.onMouseOver,
        		scope: this
        	},
        	"mouseout": {
        		fn: this.onMouseOut,
        		scope: this
        	}
        };
        
        ul.on(ulListeners);
        
        this.items.each(
        	function(item){
	            var li = document.createElement("li");
	            li.className = "x-menu-list-item";
	            ul.dom.appendChild(li);
	            item.render(li, this);
	        }, this);

        this.ul = ul;
        this.autoWidth();

        toolsUl.on(ulListeners);
        
        this.toolItems.each(
        	function(item){
	            var li = document.createElement("li");
	            li.className = "x-menu-list-item";
	            toolsUl.dom.appendChild(li);
	            item.render(li, this);
	        }, this);
	        
        this.toolsUl = toolsUl;
        this.autoWidth();
             
        this.menuBWrap.setStyle('position', 'relative');  
        this.menuBWrap.setHeight(this.height);
        
        this.menuPanel.setStyle({
        	padding: '2px',
        	position: 'absolute',
        	overflow: 'auto'
        });
        
        this.toolsPanel.setStyle({
        	padding: '2px 4px 2px 2px',
        	position: 'absolute',
        	overflow: 'auto'
        });
        
        this.setTitle(this.title);
    },
    
    // private
    findTargetItem : function(e){
        var t = e.getTarget(".x-menu-list-item", this.ul,  true);
        if(t && t.menuItemId){
        	if(this.items.get(t.menuItemId)){
            	return this.items.get(t.menuItemId);
            }else{
            	return this.toolItems.get(t.menuItemId);
            }
        }
    },

    /**
     * Displays this menu relative to another element
     * @param {Mixed} element The element to align to
     * @param {String} position (optional) The {@link Ext.Element#alignTo} anchor position to use in aligning to
     * the element (defaults to this.defaultAlign)
     * @param {Ext.ux.StartMenu} parentMenu (optional) This menu's parent menu, if applicable (defaults to undefined)
     */
    show : function(el, pos, parentMenu){
        this.parentMenu = parentMenu;
        if(!this.el){
            this.render();
        }

        this.fireEvent("beforeshow", this);
        this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign), parentMenu, false);
        
        var tPanelWidth = 100;      
        var box = this.menuBWrap.getBox();
        this.menuPanel.setWidth(box.width-tPanelWidth);
        this.menuPanel.setHeight(box.height);
        
        this.toolsPanel.setWidth(tPanelWidth);
        this.toolsPanel.setX(box.x+box.width-tPanelWidth);
        this.toolsPanel.setHeight(box.height);
    },
    
    addTool : function(){
        var a = arguments, l = a.length, item;
        for(var i = 0; i < l; i++){
            var el = a[i];
            if(el.render){ // some kind of Item
                item = this.addToolItem(el);
            }else if(typeof el == "string"){ // string
                if(el == "separator" || el == "-"){
                    item = this.addToolSeparator();
                }else{
                    item = this.addText(el);
                }
            }else if(el.tagName || el.el){ // element
                item = this.addElement(el);
            }else if(typeof el == "object"){ // must be menu item config?
                item = this.addToolMenuItem(el);
            }
        }
        return item;
    },
    
    /**
     * Adds a separator bar to the Tools
     * @return {Ext.menu.Item} The menu item that was added
     */
    addToolSeparator : function(){
        return this.addToolItem(new Ext.menu.Separator({itemCls: 'ux-toolmenu-sep'}));
    },

    addToolItem : function(item){
        this.toolItems.add(item);
        if(this.ul){
            var li = document.createElement("li");
            li.className = "x-menu-list-item";
            this.ul.dom.appendChild(li);
            item.render(li, this);
            this.delayAutoWidth();
        }
        return item;
    },

    addToolMenuItem : function(config){
        if(!(config instanceof Ext.menu.Item)){
            if(typeof config.checked == "boolean"){ // must be check menu item config?
                config = new Ext.menu.CheckItem(config);
            }else{
                config = new Ext.menu.Item(config);
            }
        }
        return this.addToolItem(config);
    },
    
    setTitle : function(title, iconCls){
        this.title = title;
        this.header.child('span').update(title);
        return this;
    }
});

/**
 * @class Ext.ux.TaskBar
 * @extends Ext.util.Observable
 */
Ext.ux.TaskBar = function(app){
    this.app = app;
    this.init();
}
//定制的WINDOWS桌面布局
Ext.extend(Ext.ux.TaskBar, Ext.util.Observable, {
    init : function(){
		this.startMenu = new Ext.ux.StartMenu(Ext.apply({
			iconCls: 'user',
			height: 300,
			shadow: true,
			title: '新卓越项目管理系统',
			width: 300
		}, this.app.startConfig));
		
		this.startBtn = new Ext.Button({
            text: '开始',
            id: 'ux-startbutton',
            iconCls:'start',
            menu: this.startMenu,
            menuAlign: 'bl-tl',
            renderTo: 'ux-taskbar-start',
            clickEvent:'mousedown',
            template: new Ext.Template(
				'<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
				'<td class="ux-startbutton-left"><i>&#160;</i></td><td class="ux-startbutton-center"><em unselectable="on"><button class="x-btn-text" type="{1}" style="height:30px;">{0}</button></em></td><td class="ux-startbutton-right"><i>&#160;</i></td>',
				"</tr></tbody></table>")
        });
        
        var width = Ext.get('ux-startbutton').getWidth()+10;
        
        var sbBox = new Ext.BoxComponent({
			el: 'ux-taskbar-start',
	        id: 'TaskBarStart',
	        minWidth: width,
			region:'west',
			split: true,
			width: width
		});
		
		this.tbPanel = new Ext.ux.TaskButtonsPanel({
			el: 'ux-taskbuttons-panel',
			id: 'TaskBarButtons',
			region:'center'
		});
				
        var container = new Ext.ux.TaskBarContainer({
			el: 'ux-taskbar',
			layout: 'border',
			items: [sbBox,this.tbPanel]
		});
		
		return this;
    },
    
    addTaskButton : function(win){
		return this.tbPanel.addButton(win, 'ux-taskbuttons-panel');
	},
	
	removeTaskButton : function(btn){
		this.tbPanel.removeButton(btn);
	},
	
	setActiveButton : function(btn){
		this.tbPanel.setActiveButton(btn);
	}
});

/**
 * @class Ext.ux.TaskBarContainer
 * @extends Ext.Container
 */
Ext.ux.TaskBarContainer = Ext.extend(Ext.Container, {
    initComponent : function() {
        Ext.ux.TaskBarContainer.superclass.initComponent.call(this);
        
        this.el = Ext.get(this.el) || Ext.getBody();
        this.el.setHeight = Ext.emptyFn;
        this.el.setWidth = Ext.emptyFn;
        this.el.setSize = Ext.emptyFn;
        this.el.setStyle({
            overflow:'hidden',
            margin:'0',
            border:'0 none'
        });
        this.el.dom.scroll = 'no';
        this.allowDomMove = false;
        this.autoWidth = true;
        this.autoHeight = true;
        Ext.EventManager.onWindowResize(this.fireResize, this);
        this.renderTo = this.el;
    },

    fireResize : function(w, h){
        this.fireEvent('resize', this, w, h, w, h);
    }
});



/**
 * @class Ext.ux.TaskButtonsPanel
 * @extends Ext.BoxComponent
 */
Ext.ux.TaskButtonsPanel = Ext.extend(Ext.BoxComponent, {
	activeButton: null,
	enableScroll: true,
	scrollIncrement: 0,
    scrollRepeatInterval: 400,
    scrollDuration: .35,
    animScroll: true,
    resizeButtons: true,
    buttonWidth: 168,
    minButtonWidth: 118,
    buttonMargin: 2,
    buttonWidthSet: false,
	
	initComponent : function() {
        Ext.ux.TaskButtonsPanel.superclass.initComponent.call(this);
        this.on('resize', this.delegateUpdates);
        this.items = [];
        
        this.stripWrap = Ext.get(this.el).createChild({
        	cls: 'ux-taskbuttons-strip-wrap',
        	cn: {
            	tag:'ul', cls:'ux-taskbuttons-strip'
            }
		});
        this.stripSpacer = Ext.get(this.el).createChild({
        	cls:'ux-taskbuttons-strip-spacer'
        });
        this.strip = new Ext.Element(this.stripWrap.dom.firstChild);
        
        this.edge = this.strip.createChild({
        	tag:'li',
        	cls:'ux-taskbuttons-edge'
        });
        this.strip.createChild({
        	cls:'x-clear'
        });
	},
	
	addButton : function(win){
		var li = this.strip.createChild({tag:'li'}, this.edge); // insert before the edge
        var btn = new Ext.ux.TaskBar.TaskButton(win, li);
		
		this.items.push(btn);
		
		if(!this.buttonWidthSet){
			this.lastButtonWidth = btn.container.getWidth();
		}
		
		this.setActiveButton(btn);
		return btn;
	},
	
	removeButton : function(btn){
		var li = document.getElementById(btn.container.id);
		btn.destroy();
		li.parentNode.removeChild(li);
		
		var s = [];
		for(var i = 0, len = this.items.length; i < len; i++) {
			if(this.items[i] != btn){
				s.push(this.items[i]);
			}
		}
		this.items = s;
		
		this.delegateUpdates();
	},
	
	setActiveButton : function(btn){
		this.activeButton = btn;
		this.delegateUpdates();
	},
	
	delegateUpdates : function(){
		/*if(this.suspendUpdates){
            return;
        }*/
        if(this.resizeButtons && this.rendered){
            this.autoSize();
        }
        if(this.enableScroll && this.rendered){
            this.autoScroll();
        }
    },
    
    autoSize : function(){
        var count = this.items.length;
        var ow = this.el.dom.offsetWidth;
        var aw = this.el.dom.clientWidth;

        if(!this.resizeButtons || count < 1 || !aw){ // !aw for display:none
            return;
        }
        
        var each = Math.max(Math.min(Math.floor((aw-4) / count) - this.buttonMargin, this.buttonWidth), this.minButtonWidth); // -4 for float errors in IE
        var btns = this.stripWrap.dom.getElementsByTagName('button');
        
        this.lastButtonWidth = Ext.get(btns[0].id).findParent('li').offsetWidth;
        
        for(var i = 0, len = btns.length; i < len; i++) {            
            var btn = btns[i];
            
            var tw = Ext.get(btns[i].id).findParent('li').offsetWidth;
            var iw = btn.offsetWidth;
            
            btn.style.width = (each - (tw-iw)) + 'px';
        }
    },
    
    autoScroll : function(){
    	var count = this.items.length;
        var ow = this.el.dom.offsetWidth;
        var tw = this.el.dom.clientWidth;
        
        var wrap = this.stripWrap;
        var cw = wrap.dom.offsetWidth;
        var pos = this.getScrollPos();
        var l = this.edge.getOffsetsTo(this.stripWrap)[0] + pos;
        
        if(!this.enableScroll || count < 1 || cw < 20){ // 20 to prevent display:none issues
            return;
        }
        
        wrap.setWidth(tw); // moved to here because of problem in Safari
        
        if(l <= tw){
            wrap.dom.scrollLeft = 0;
            //wrap.setWidth(tw); moved from here because of problem in Safari
            if(this.scrolling){
                this.scrolling = false;
                this.el.removeClass('x-taskbuttons-scrolling');
                this.scrollLeft.hide();
                this.scrollRight.hide();
            }
        }else{
            if(!this.scrolling){
                this.el.addClass('x-taskbuttons-scrolling');
            }
            tw -= wrap.getMargins('lr');
            wrap.setWidth(tw > 20 ? tw : 20);
            if(!this.scrolling){
                if(!this.scrollLeft){
                    this.createScrollers();
                }else{
                    this.scrollLeft.show();
                    this.scrollRight.show();
                }
            }
            this.scrolling = true;
            if(pos > (l-tw)){ // ensure it stays within bounds
                wrap.dom.scrollLeft = l-tw;
            }else{ // otherwise, make sure the active button is still visible
				this.scrollToButton(this.activeButton, true); // true to animate
            }
            this.updateScrollButtons();
        }
    },

    createScrollers : function(){
        var h = this.el.dom.offsetHeight; //var h = this.stripWrap.dom.offsetHeight;
		
        // left
        var sl = this.el.insertFirst({
            cls:'ux-taskbuttons-scroller-left'
        });
        sl.setHeight(h);
        sl.addClassOnOver('ux-taskbuttons-scroller-left-over');
        this.leftRepeater = new Ext.util.ClickRepeater(sl, {
            interval : this.scrollRepeatInterval,
            handler: this.onScrollLeft,
            scope: this
        });
        this.scrollLeft = sl;

        // right
        var sr = this.el.insertFirst({
            cls:'ux-taskbuttons-scroller-right'
        });
        sr.setHeight(h);
        sr.addClassOnOver('ux-taskbuttons-scroller-right-over');
        this.rightRepeater = new Ext.util.ClickRepeater(sr, {
            interval : this.scrollRepeatInterval,
            handler: this.onScrollRight,
            scope: this
        });
        this.scrollRight = sr;
    },
    
    getScrollWidth : function(){
        return this.edge.getOffsetsTo(this.stripWrap)[0] + this.getScrollPos();
    },

    getScrollPos : function(){
        return parseInt(this.stripWrap.dom.scrollLeft, 10) || 0;
    },

    getScrollArea : function(){
        return parseInt(this.stripWrap.dom.clientWidth, 10) || 0;
    },

    getScrollAnim : function(){
        return {
        	duration: this.scrollDuration,
        	callback: this.updateScrollButtons,
        	scope: this
        };
    },

    getScrollIncrement : function(){
    	return (this.scrollIncrement || this.lastButtonWidth+2);
    },
    
    /* getBtnEl : function(item){
        return document.getElementById(item.id);
    }, */
    
    scrollToButton : function(item, animate){
    	item = item.el.dom.parentNode; // li
        if(!item){ return; }
        var el = item; //this.getBtnEl(item);
        var pos = this.getScrollPos(), area = this.getScrollArea();
        var left = Ext.fly(el).getOffsetsTo(this.stripWrap)[0] + pos;
        var right = left + el.offsetWidth;
        if(left < pos){
            this.scrollTo(left, animate);
        }else if(right > (pos + area)){
            this.scrollTo(right - area, animate);
        }
    },
    
    scrollTo : function(pos, animate){
        this.stripWrap.scrollTo('left', pos, animate ? this.getScrollAnim() : false);
        if(!animate){
            this.updateScrollButtons();
        }
    },
    
    onScrollRight : function(){
        var sw = this.getScrollWidth()-this.getScrollArea();
        var pos = this.getScrollPos();
        var s = Math.min(sw, pos + this.getScrollIncrement());
        if(s != pos){
        	this.scrollTo(s, this.animScroll);
        }        
    },

    onScrollLeft : function(){
        var pos = this.getScrollPos();
        var s = Math.max(0, pos - this.getScrollIncrement());
        if(s != pos){
            this.scrollTo(s, this.animScroll);
        }
    },
    
    updateScrollButtons : function(){
        var pos = this.getScrollPos();
        this.scrollLeft[pos == 0 ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-left-disabled');
        this.scrollRight[pos >= (this.getScrollWidth()-this.getScrollArea()) ? 'addClass' : 'removeClass']('ux-taskbuttons-scroller-right-disabled');
    }
});



/**
 * @class Ext.ux.TaskBar.TaskButton
 * @extends Ext.Button
 */
Ext.ux.TaskBar.TaskButton = function(win, el){
	this.win = win;
    Ext.ux.TaskBar.TaskButton.superclass.constructor.call(this, {
        iconCls: win.iconCls,
        text: Ext.util.Format.ellipsis(win.title, 12),
        renderTo: el,
        handler : function(){
            if(win.minimized || win.hidden){
                win.show();
            }else if(win == win.manager.getActive()){
                win.minimize();
            }else{
                win.toFront();
            }
        },
        clickEvent:'mousedown',
        template: new Ext.Template(
			'<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
			'<td class="ux-taskbutton-left"><i>&#160;</i></td><td class="ux-taskbutton-center"><em unselectable="on"><button class="x-btn-text" type="{1}" style="height:28px;">{0}</button></em></td><td class="ux-taskbutton-right"><i>&#160;</i></td>',
			"</tr></tbody></table>")
    });
};

Ext.extend(Ext.ux.TaskBar.TaskButton, Ext.Button, {
    onRender : function(){
        Ext.ux.TaskBar.TaskButton.superclass.onRender.apply(this, arguments);

        this.cmenu = new Ext.menu.Menu({
            items: [{
                text: 'Restore',
                handler: function(){
                    if(!this.win.isVisible()){
                        this.win.show();
                    }else{
                        this.win.restore();
                    }
                },
                scope: this
            },{
                text: 'Minimize',
                handler: this.win.minimize,
                scope: this.win
            },{
                text: 'Maximize',
                handler: this.win.maximize,
                scope: this.win
            }, '-', {
                text: 'Close',
                handler: this.closeWin.createDelegate(this, this.win, true),
                scope: this.win
            }]
        });

        this.cmenu.on('beforeshow', function(){
            var items = this.cmenu.items.items;
            var w = this.win;
            items[0].setDisabled(w.maximized !== true && w.hidden !== true);
            items[1].setDisabled(w.minimized === true);
            items[2].setDisabled(w.maximized === true || w.hidden === true);
        }, this);

        this.el.on('contextmenu', function(e){
            e.stopEvent();
            if(!this.cmenu.el){
                this.cmenu.render();
            }
            var xy = e.getXY();
            xy[1] -= this.cmenu.el.getHeight();
            this.cmenu.showAt(xy);
        }, this);
    },
    
    closeWin : function(cMenu, e, win){
		if(!win.isVisible()){
			win.show();
		}else{
			win.restore();
		}
		win.close();
	}
});

/**
 * @class Ext.ux.TreeCheckNodeUI
 * @extends Ext.tree.TreeNodeUI
 * 
 * 对 Ext.tree.TreeNodeUI 进行checkbox功能的扩展,后台返回的结点信息不用非要包含checked属性
 * 
 * 扩展的功能点有：
 * 一、支持只对树的叶子进行选择
 *    只有当返回的树结点属性leaf = true 时，结点才有checkbox可选
 * 	  使用时，只需在声明树时，加上属性 onlyLeafCheckable: true 既可，默认是false
 * 
 * 二、支持对树的单选
 *    只允许选择一个结点
 * 	  使用时，只需在声明树时，加上属性 checkModel: "single" 既可
 * 
 * 二、支持对树的级联多选 
 *    当选择结点时，自动选择该结点下的所有子结点，或该结点的所有父结点（根结点除外），特别是支持异步，当子结点还没显示时，会从后台取得子结点，然后将其选中/取消选中
 *    使用时，只需在声明树时，加上属性 checkModel: "cascade" 或"parentCascade"或"childCascade"既可
 * 
 * 三、添加"check"事件
 *    该事件会在树结点的checkbox发生改变时触发
 *    使用时，只需给树注册事件,如：
 *    tree.on("check",function(node,checked){...});
 * 
 * 默认情况下，checkModel为'multiple'，也就是多选，onlyLeafCheckable为false，所有结点都可选
 * 
 * 使用方法：在loader里加上 baseAttrs:{uiProvider:Ext.ux.TreeCheckNodeUI} 既可.
 * 例如：
 *   var tree = new Ext.tree.TreePanel({
 *		el:'tree-ct',
 *		width:568,
 *		height:300,
 *		checkModel: 'cascade',   //对树的级联多选
 *		onlyLeafCheckable: false,//对树所有结点都可选
 *		animate: false,
 *		rootVisible: false,
 *		autoScroll:true,
 *		loader: new Ext.tree.DWRTreeLoader({
 *			dwrCall:Tmplt.getTmpltTree,
 *			baseAttrs: { uiProvider: Ext.ux.TreeCheckNodeUI } //添加 uiProvider 属性
 *		}),
 *		root: new Ext.tree.AsyncTreeNode({ id:'0' })
 *	});
 *	tree.on("check",function(node,checked){alert(node.text+" = "+checked)}); //注册"check"事件
 *	tree.render();
 * 
 */

Ext.ux.TreeCheckNodeUI = function() {
	//多选: 'multiple'(默认)
	//单选: 'single'
	//级联多选: 'cascade'(同时选父和子);'parentCascade'(选父);'childCascade'(选子)
	this.checkModel = 'multiple';
	
	//only leaf can checked
	this.onlyLeafCheckable = false;
	
	Ext.ux.TreeCheckNodeUI.superclass.constructor.apply(this, arguments);
};

Ext.extend(Ext.ux.TreeCheckNodeUI, Ext.tree.TreeNodeUI, {

	/**
     * @cfg {String} checkedCls The CSS class to use when the control is checked (defaults to 'x-form-check-checked').
     * Note that this class applies to both checkboxes and radio buttons and is added to the control's wrapper element.
     */
    checkedCls: 'x-form-check-checked',
    /**
     * @cfg {String} focusCls The CSS class to use when the control receives input focus (defaults to 'x-form-check-focus').
     * Note that this class applies to both checkboxes and radio buttons and is added to the control's wrapper element.
     */
    focusCls: 'x-form-check-focus',
    /**
     * @cfg {String} overCls The CSS class to use when the control is hovered over (defaults to 'x-form-check-over').
     * Note that this class applies to both checkboxes and radio buttons and is added to the control's wrapper element.
     */
    overCls: 'x-form-check-over',
    /**
     * @cfg {String} mouseDownCls The CSS class to use when the control is being actively clicked (defaults to 'x-form-check-down').
     * Note that this class applies to both checkboxes and radio buttons and is added to the control's wrapper element.
     */
    mouseDownCls: 'x-form-check-down',
	
    // private
    //baseCls: 'x-form-check',
	
    renderElements : function(n, a, targetNode, bulkRender){
    	var tree = n.getOwnerTree();
		this.checkModel = tree.checkModel || this.checkModel;
		this.onlyLeafCheckable = tree.onlyLeafCheckable || false;
    	
        // add some indent caching, this helps performance when rendering a large tree
        this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';

        //var cb = typeof a.checked == 'boolean';
		var cb = (!this.onlyLeafCheckable || a.leaf);
        var href = a.href ? a.href : Ext.isGecko ? "" : "#";
        var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow" />',
            '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on" />',
            cb ? ('<span class="x-tree-checkbox-wrap '+(a.checked ? 'x-form-check-checked"':'"')+'" ><span class="x-tree-checkbox-wrap-inner"><img src="'+Ext.BLANK_IMAGE_URL+'" class="x-form-check" /></span></span>') : '',
            '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span unselectable="on">',n.text,"</span></a></div>",
            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
            "</li>"].join('');

        var nel;
        if(bulkRender !== true && n.nextSibling && (nel = n.nextSibling.ui.getEl())){
            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
        }else{
            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
        }
        
        this.elNode = this.wrap.childNodes[0];
        this.ctNode = this.wrap.childNodes[1];
        var cs = this.elNode.childNodes;
        this.indentNode = cs[0];
        this.ecNode = cs[1];
        this.iconNode = cs[2];
        var index = 3;
        if(cb){
            this.checkboxWrap = cs[3];
            //this.checkbox = cs[3];//让包装就是checkbox
            Ext.fly(this.checkboxWrap.firstChild).addClassOnOver(this.overCls);
            Ext.fly(this.checkboxWrap).on('click', this.check.createDelegate(this,[null]));
            //Ext.fly(this.checkbox).on('click', this.check.createDelegate(this,[null]));
            index++;
        }
        this.anchor = cs[index];
        this.textNode = cs[index].firstChild;
    },
    // 获取所有被选择的结点的id数组++++++++++++++++++++++++++++++++++++++++++++++++++
    getChecked : function(node){
		var checked = [], i;
		if( typeof node == 'undefined' ) {
			node = this.rootVisible ? this.getRootNode() : this.getRootNode().childNodes;
		}
		if (!Ext.isArray(node)) {
			node = [node];
		}
		var f = function(){
			if (this.attributes.checked) {
				checked.push(this.id+"|"+(this.clicked===true)+"|"+(this.childrenRendered===true));
			}
		};
		Ext.each(node, function(n){
			n.cascade(f);
		});
		return checked;
	},
    // ++++++++++++++++++++++++++++++++++++++++++++++++++
    
    // private 绑定在每一个checkbox上的单击监听器
    check : function(){
        var n = this.node;
		var tree = n.getOwnerTree();
		
		var checked = arguments[0]||!n.attributes.checked;
		//在这里添加样式逻辑
		if (checked) {
			Ext.fly(this.checkboxWrap).addClass(this.checkedCls);
		} else {
			Ext.fly(this.checkboxWrap).removeClass(this.checkedCls);
		}
		
		//设置结点的选中属性
		n.attributes.checked = checked;
		this.node.clicked=true;//标记此结点被点击过
		//发布check事件
		tree.fireEvent('check', n, checked);
		
		//单选模式,只需要取消前面被选中的结点
		if(this.checkModel == 'single'){
			var checkedNodes = tree.getChecked();
			for(var i=0;i<checkedNodes.length;i++){
				var node = checkedNodes[i];
				if(node.id != n.id){
					Ext.fly(node.getUI().checkboxWrap).removeClass(this.checkedCls);//在这里去除样式
					node.attributes.checked = false;
					tree.fireEvent('check', node, false);
				}
			}
		} else if(!this.onlyLeafCheckable){//级联与onlyLeafCheckable是互斥的
			if(this.checkModel == 'cascadeLocal'){
				if( !n.expanded && n.childrenRendered ) {
					//n.expand(false,false,this.childCheck);
					this.childCheck(n);
				}else {
					this.childCheck(n);  
				}
			}
			if(this.checkModel == 'cascadeLocal'||this.checkModel == 'cascade' || this.checkModel == 'parentCascade'){
				var parentNode = n.parentNode;
				if(parentNode !== null) {
					this.parentCheck(parentNode,checked);
				}
			}
			if(this.checkModel == 'cascade' || this.checkModel == 'childCascade'){
				if( !n.expanded && !n.childrenRendered ) {
					n.expand(false,false,this.childCheck);
				}else {
					this.childCheck(n);  
				}
			}
		}
	},

    
    // private 设置子结点的状态(调用此方法必须保证子结点已经被渲染过了)//父类中没有此方法
	childCheck : function(node){
		var a = node.attributes;
		if(!a.leaf) {
			var cs = node.childNodes;
			for(var i = 0; i < cs.length; i++) {
				cs[i].getUI().check(a.checked);
			}
		}
	},
	
	// private 设置父结点的状态//父类中没有此方法
	parentCheck : function(node ,checked){
		if (node.isRoot) {
			return;
		}
		//如果二者状态一样则直接返回
		if(!(checked ^ node.attributes.checked))return;
		//如果当前结点有被选中的子结点,虽然当前结点要被设置未选中状态,但是因为还有子结点被选择，所以不改变状态
		if(!checked && this.childHasChecked(node))return;
		node.attributes.checked = checked;
		node.getOwnerTree().fireEvent('check', node, checked);
		//在这里添加样式逻辑
		if (checked) {
			Ext.fly(node.getUI().checkboxWrap).addClass(node.getUI().checkedCls);
		} else {
			Ext.fly(node.getUI().checkboxWrap).removeClass(node.getUI().checkedCls);
		}
		this.node.clicked=true;//标记此结点被点击过
		var parentNode = node.parentNode;
		if( parentNode !== null){
			this.parentCheck(parentNode,checked);
		}
	},
	
	// private 当前结点是否有被选中的子结点//父类中没有此方法
	childHasChecked : function(node){
		var childNodes = node.childNodes;
		if(childNodes || childNodes.length>0){
			for(var i=0;i<childNodes.length;i++){
				if(childNodes[i].attributes.checked)
					return true;
			}
		}
		return false;
	},
	
     //主要是为了渲染所有的子结点//此类在父类方法中是没有的
    expandAll : function(node){
    	node = node || this.node;
    	if( !this.node.expanded && !this.node.childrenRendered ) {
			this.node.expand(false,false);
			this.node.collapse(false,false);
    	}
    	if(!this.node.attributes.leaf) {
			var cs = this.node.childNodes;
			var csui;
			for(var i = 0; i < cs.length; i++) {
				csui = cs[i].getUI();
				csui.expandAll();
			}
		}
    },
    
    //此类在父类方法是没有
    resetChecked : function(node){
    	node = node || this.node;
    	var f = function(){
    		//在这里除去样式逻辑
			Ext.fly(this.ui.checkboxWrap).removeClass(this.ui.checkedCls);
    		//this.ui.check(false);
			this.attributes.checked = false;
    		this.clicked = undefined;
    	}
    	node.cascade(f);
    },
    
    //此类在父类方法是没有
    setChecked : function(checks, node){
    	node = node || this.node;
    	var f = function(){
    		if (!node.isRoot&&checks.indexOf(","+this.id+",")>0) {
    			//在这里添加样式逻辑
				Ext.fly(this.ui.checkboxWrap).addClass(this.ui.checkedCls);
				
				//设置结点的选中属性
				this.attributes.checked = true;
				//发布check事件
				this.getOwnerTree().fireEvent('check', this, true);
    		}
    	}
    	node.cascade(f);
    }
});


Ext.ux.TimeField=function(config)
{
    //be true when reset

    this.dateTime=config.dateTime;
    Ext.ux.TimeField.superclass.constructor.call(this,config);
};

Ext.extend(Ext.ux.TimeField,Ext.form.TimeField, {
     
     /**//**
     * Clear any invalid styles/messages for this field
     */
    clearInvalid : function(){
        if(!this.rendered || this.preventMark){ // not rendered
            return;
        }
        this.el.removeClass(this.invalidClass);
        this.dateTime.clearInvalid();
        //check the other field for datetime
        //this.dateTime.df.isValid();
        
    },
    /**//**
     * Mark this field as invalid
     * @param {String} msg The validation message
     */
    markInvalid : function(msg){
        if(!this.rendered || this.preventMark){ // not rendered
            return;
        }
        this.el.addClass(this.invalidClass);
        msg = msg || this.invalidText;
        this.dateTime.markInvalid(msg);
    }
   
    
});
Ext.ux.DateField=function(config)
{
    //be true when reset
    this.isReset=false;
    this.dateTime=config.dateTime;
    Ext.ux.DateField.superclass.constructor.call(this,config);
};

Ext.extend(Ext.ux.DateField,Ext.form.DateField,  {
     
     /**//**
     * Clear any invalid styles/messages for this field
     */
    clearInvalid : function(){
        if(!this.rendered || this.preventMark){ // not rendered
            return;
        }
        this.el.removeClass(this.invalidClass);
         this.dateTime.clearInvalid();
         //check the other field for datetime
        
        // this.dateTime.tf.isValid();
    },
    /**//**
     * Mark this field as invalid
     * @param {String} msg The validation message
     */
    markInvalid : function(msg){
        if(!this.rendered || this.preventMark){ // not rendered
            return;
        }
        this.el.addClass(this.invalidClass);
        msg = msg || this.invalidText;
         this.dateTime.markInvalid(msg);
    }
   
})

Ext.ux.DateTime = function(config) {

 // create DateField
 
 //message stack
 this.messages=new Array();
 var dateTime=this;
        var dateConfig = Ext.apply({}, {
             name:config.name + '-date'
            ,format:config.dateFormat || Ext.form.DateField.prototype.format
            ,width:config.dateWidth
            ,selectOnFocus:config.selectOnFocus
            ,dateTime:dateTime
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, config.dateConfig);
        this.df = new Ext.ux.DateField(dateConfig);
       

        // create TimeField
        var timeConfig = Ext.apply({}, {
             name:config.name + '-time'
            ,format:config.timeFormat || Ext.form.TimeField.prototype.format
            ,width:config.timeWidth
            ,selectOnFocus:config.selectOnFocus
            ,dateTime:dateTime
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, config.timeConfig);
        this.tf = new Ext.ux.TimeField(timeConfig);
        Ext.ux.DateTime.superclass.constructor.call(this,config);
        
        
};

Ext.extend(Ext.ux.DateTime ,Ext.form.Field, {
    /**//**
     * @cfg {String/Object} defaultAutoCreate DomHelper element spec
     * Let superclass to create hidden field instead of textbox. Hidden will be submittend to server
     */
     defaultAutoCreate:{tag:'input', type:'hidden'}
    /**//**
     * @cfg {Number} timeWidth Width of time field in pixels (defaults to 100)
     */
    ,timeWidth:80
    /**//**
     * @cfg {String} dtSeparator Date - Time separator. Used to split date and time (defaults to ' ' (space))
     */
    ,dtSeparator:' '
    /**//**
     * @cfg {String} hiddenFormat Format of datetime used to store value in hidden field
     * and submitted to server (defaults to 'Y-m-d H:i:s' that is mysql format)
     */
    ,hiddenFormat:'Y-m-d H:i:s'
    /**//**
     * @cfg {Boolean} otherToNow Set other field to now() if not explicly filled in (defaults to true)
     */
    ,otherToNow:true
    /**//**
     * @cfg {Boolean} emptyToNow Set field value to now if on attempt to set empty value.
     * If it is true then setValue() sets value of field to current date and time (defaults to false)
    /**
     * @cfg {String} timePosition Where the time field should be rendered. 'right' is suitable for forms
     * and 'bellow' is suitable if the field is used as the grid editor (defaults to 'right')
     */
    ,timePosition:'right' // valid values:'bellow', 'right'
    /**//**
     * @cfg {String} dateFormat Format of DateField. Can be localized. (defaults to 'm/y/d')
     */
    ,dateFormat:'m/d/y'
    /**//**
     * @cfg {String} timeFormat Format of TimeField. Can be localized. (defaults to 'g:i A')
     */
    ,timeFormat:'g:i A'
    /**//**
     * @cfg {Object} dateConfig Config for DateField constructor.
     */
    /**//**
     * @cfg {Object} timeConfig Config for TimeField constructor.
     */

    // {{{
    /**//**
     * private
     * creates DateField and TimeField and installs the necessary event handlers
     */
    ,initComponent:function() {
        // call parent initComponent
        Ext.ux.DateTime.superclass.initComponent.call(this);
        // relay events
        this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
        this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);


    } // eo function initComponent
    // }}}
    // {{{
    /**//**
     * private
     * Renders underlying DateField and TimeField and provides a workaround for side error icon bug
     */
    ,onRender:function(ct, position) {
        // don't run more than once
        if(this.isRendered) {
            return;
        }

        // render underlying hidden field
        Ext.ux.DateTime.superclass.onRender.call(this, ct, position);

        // render DateField and TimeField
        // create bounding table
        var t;
        if('bellow' === this.timePosition) {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                 {tag:'tr',children:[{tag:'td', style:'padding-bottom:1px', cls:'ux-datetime-date'}]}
                ,{tag:'tr',children:[{tag:'td', cls:'ux-datetime-time'}]}
            ]}, true);
        }
        else {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                {tag:'tr',children:[
                    {tag:'td',style:'padding-right:4px', cls:'ux-datetime-date'},{tag:'td', cls:'ux-datetime-time'}
                ]}
            ]}, true);
        }

        this.tableEl = t;
        this.wrap = t.wrap({cls:'x-form-field-wrap'});
        this.wrap.on("mousedown", this.onMouseDown, this, {delay:10});

        // render DateField & TimeField
        this.df.render(t.child('td.ux-datetime-date'));
        this.tf.render(t.child('td.ux-datetime-time'));

        // workaround for IE trigger misalignment bug
        if(Ext.isIE && Ext.isStrict) {
            t.select('input').applyStyles({top:0});
        }

        this.on('specialkey', this.onSpecialKey, this);
        this.df.el.swallowEvent(['keydown', 'keypress']);
        this.tf.el.swallowEvent(['keydown', 'keypress']);

        // create icon for side invalid errorIcon
        if('side' === this.msgTarget) {
            var elp = this.el.findParent('.x-form-element', 10, true);
            this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});
            this.df.errorIcon = this.errorIcon;
            this.tf.errorIcon = this.errorIcon;
        }
        
        // we're rendered flag
        this.isRendered = true;

    } // eo function onRender
    // }}}
    // {{{
    /**//**
     * private
     */
    ,adjustSize:Ext.BoxComponent.prototype.adjustSize
    // }}}
    // {{{
    /**//**
     * private
     */
    ,alignErrorIcon:function() {
        this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
    }
    // }}}
    // {{{
    /**//**
     * private initializes internal dateValue
     */
    ,initDateValue:function() {
        this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
    }
    // }}}
    // {{{
    /**//**
     * Disable this component.
     * @return {Ext.Component} this
     */
    ,disable:function() {
        if(this.isRendered) {
            this.df.disabled = this.disabled;
            this.df.onDisable();
            this.tf.onDisable();
        }
        this.disabled = true;
        this.df.disabled = true;
        this.tf.disabled = true;
        this.fireEvent("disable", this);
        return this;
    } // eo function disable
    // }}}
    // {{{
    /**//**
     * Enable this component.
     * @return {Ext.Component} this
     */
    ,enable:function() {
        if(this.rendered){
            this.df.onEnable();
            this.tf.onEnable();
        }
        this.disabled = false;
        this.df.disabled = false;
        this.tf.disabled = false;
        this.fireEvent("enable", this);
        return this;
    } // eo function enable
    // }}}
    // {{{
    /**//**
     * private Focus date filed
     */
    ,focus:function() {
        this.df.focus();
    } // eo function focus
    // }}}
    // {{{
    /**//**
     * private
     */
    ,getPositionEl:function() {
        return this.wrap;
    }
    // }}}
    // {{{
    /**//**
     * private
     */
    ,getResizeEl:function() {
        return this.wrap;
    }
    // }}}
    // {{{
    /**//**
     * @return {Date/String} Returns value of this field
     */
    ,getValue:function() {
        // create new instance of date
        return this.dateValue ? new Date(this.dateValue) : '';
    } // eo function getValue
    // }}}
    // {{{
    /**//**
     * @return {Boolean} true = valid, false = invalid
     * private Calls isValid methods of underlying DateField and TimeField and returns the result
     */
    ,isValid:function() {
        return this.df.isValid() && this.tf.isValid();
    } // eo function isValid
    // }}}
    // {{{
    /**//**
     * Returns true if this component is visible
     * @return {boolean} 
     */
    ,isVisible : function(){
        return this.df.rendered && this.df.getActionEl().isVisible();
    } // eo function isVisible
    // }}}
    // {{{
    /**//** 
     * private Handles blur event
     */
    ,onBlur:function(f) {
        // called by both DateField and TimeField blur events

        // revert focus to previous field if clicked in between
        if(this.wrapClick) {
            f.focus();
            this.wrapClick = false;
        }

        // update underlying value
        if(f === this.df) {
            this.updateDate();
        }
        else {
            this.updateTime();
        }
        this.updateHidden();

        // fire events later
        (function() {
            if(!this.df.hasFocus && !this.tf.hasFocus) {
                var v = this.getValue();
                if(String(v) !== String(this.startValue)) {
                    this.fireEvent("change", this, v, this.startValue);
                }
                this.hasFocus = false;
                this.fireEvent('blur', this);
            }
        }).defer(100, this);

    } // eo function onBlur
    // }}}
    // {{{
    /**//**
     * private Handles focus event
     */
    ,onFocus:function() {
        if(!this.hasFocus){
            this.hasFocus = true;
            this.startValue = this.getValue();
            this.fireEvent("focus", this);
        }
    }
    // }}}
    // {{{
    /**//**
     * private Just to prevent blur event when clicked in the middle of fields
     */
    ,onMouseDown:function(e) {
        this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
    }
    // }}}
    // {{{
    /**//**
     * private
     * Handles Tab and Shift-Tab events
     */
    ,onSpecialKey:function(t, e) {
        var key = e.getKey();
        if(key == e.TAB) {
            if(t === this.df && !e.shiftKey) {
                e.stopEvent();
                this.tf.focus();
            }
            if(t === this.tf && e.shiftKey) {
                e.stopEvent();
                this.df.focus();
            }
        }
        // otherwise it misbehaves in editor grid
        if(key == e.ENTER) {
            this.updateValue();
        }

    } // eo function onSpecialKey
    // }}}
    // {{{
    /**//**
     * private Sets the value of DateField
     */
    ,setDate:function(date) {
        this.df.setValue(date);
    } // eo function setDate
    // }}}
    // {{{
    /**//** 
     * private Sets the value of TimeField
     */
    ,setTime:function(date) {
        this.tf.setValue(date);
    } // eo function setTime
    // }}}
    // {{{
    /**//**
     * private
     * Sets correct sizes of underlying DateField and TimeField
     * With workarounds for IE bugs
     */
    ,setSize:function(w, h) {
        if(!w) {
            return;
        }
        if('bellow' == this.timePosition) {
            this.df.setSize(w, h);
            this.tf.setSize(w, h);
            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w);
                this.tf.el.up('td').setWidth(w);
            }
        }
        else {
            this.df.setSize(w - this.timeWidth - 4, h);
            this.tf.setSize(this.timeWidth, h);

            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w - this.timeWidth - 4);
                this.tf.el.up('td').setWidth(this.timeWidth);
            }
        }
    } // eo function setSize
    // }}}
    // {{{
    /**//**
     * @param {Mixed} val Value to set
     * Sets the value of this field
     */
    ,setValue:function(val) {
        //alert(val.time);
        if(!val && true === this.emptyToNow) {
            this.setValue(new Date());
            return;
        }
        else if(!val) {
            this.setDate('');
            this.setTime('');
            this.updateValue();
            return;
        }
        val = val ? val : new Date(1970, 0 ,1, 0, 0, 0);
        var da, time;
        if(val instanceof Date) {
            this.setDate(val);
            this.setTime(val);
            this.dateValue = new Date(val);
        }else if(val instanceof Object&&val.time)
        {
            var dtDate = new Date(parseInt(val.time));
            this.setDate(dtDate);
            this.setTime(dtDate);
            this.dateValue = new Date(dtDate);
        }
        else {
            da = val.split(this.dtSeparator);
            this.setDate(da[0]);
            if(da[1]) {
                this.setTime(da[1]);
            }
        }
        this.updateValue();
    } // eo function setValue
    // }}}
    // {{{
    /**//**
     * Hide or show this component by boolean
     * @return {Ext.Component} this
     */
    ,setVisible: function(visible){
        if(visible) {
            
            this.df.show();
            this.tf.show();

        
        }else{
            this.df.hide();
            this.tf.hide();
        }
        return this;
    } // eo function setVisible
    // }}}
    //{{{
    ,
    reset : function(){
        this.df.reset();
        this.tf.reset();
        if(this.isRendered) { 
			this.el.dom.value = ''; 
		} 
		this.clearInvalid(); 
    },
    show:function() {

        return this.setVisible(true);
    } // eo function show
    //}}}
    //{{{
    ,hide:function() {
        
        return this.setVisible(false);
    } // eo function hide
    //}}}
    // {{{
    /**//**
     * private Updates the date part
     */
    ,updateDate:function() {

        var d = this.df.getValue();
        if(d) {
            if(!(this.dateValue instanceof Date)) {
                this.initDateValue();
                if(!this.tf.getValue()) {
                    this.setTime(this.dateValue);
                }
            }
            this.dateValue.setMonth(0); // because of leap years
            this.dateValue.setFullYear(d.getFullYear());
            this.dateValue.setMonth(d.getMonth());
            this.dateValue.setDate(d.getDate());
        }
        else {
            this.dateValue = '';
            this.setTime('');
        }
    } // eo function updateDate
    // }}}
    // {{{
    /**//**
     * private
     * Updates the time part
     */
    ,updateTime:function() {
        var t = this.tf.getValue();
        if(t && !(t instanceof Date)) {
            t = Date.parseDate(t, this.tf.format);
        }
        if(t && !this.df.getValue()) {
            this.initDateValue();
            this.setDate(this.dateValue);
        }
        if(this.dateValue instanceof Date) {
            if(t) {
                this.dateValue.setHours(t.getHours());
                this.dateValue.setMinutes(t.getMinutes());
                this.dateValue.setSeconds(t.getSeconds());
            }
            else {
                this.dateValue.setHours(0);
                this.dateValue.setMinutes(0);
                this.dateValue.setSeconds(0);
            }
        }
    } // eo function updateTime
    // }}}
    // {{{
    /**//**
     * private Updates the underlying hidden field value
     */
    ,updateHidden:function() {
        if(this.isRendered) {
            var value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : '';
            this.el.dom.value = value;
        }
    }
    // }}}
    // {{{
    /**//**
     * private Updates all of Date, Time and Hidden
     */
    ,updateValue:function() {

        this.updateDate();
        this.updateTime();
        this.updateHidden();

        return;
    } // eo function updateValue
    // }}}
    // {{{
    /**//**
     * @return {Boolean} true = valid, false = invalid
     * callse validate methods of DateField and TimeField
     */
    ,validate:function() {
        return this.df.validate() && this.tf.validate();
    } // eo function validate
    // }}}
    // {{{
    /**//**
     * Returns renderer suitable to render this field
     * @param {Object} Column model config
     */
    ,renderer: function(field) {
        
        var format = field.editor.dateFormat || Ext.ux.DateTime.prototype.dateFormat;
        format += ' ' + (field.editor.timeFormat || Ext.ux.DateTime.prototype.timeFormat);
        var renderer = function(val) {
            var retval = Ext.util.Format.date(val, format);
            return retval;
        };
        return renderer;
    },
    markInvalid:function(msg)
    {
        this.messages.push(msg);
         Ext.ux.DateTime.superclass.markInvalid.call(this,msg);
    },
    clearInvalid:function()
    {
        this.messages.pop();
        if(this.messages.length==0)
        {
             Ext.ux.DateTime.superclass.clearInvalid.call(this);
        }
        else
        {
            var msg=this.messages.pop();
            this.markInvalid(msg);
        }
    }
    
    
    // }}}

}); // eo extend

// register xtype
Ext.reg('xdatetime', Ext.ux.DateTime);

Ext.ux.TabCloseMenu = function(){
    var tabs, menu, ctxItem;
    this.init = function(tp){
        tabs = tp;
        tabs.on('contextmenu', onContextMenu);
    }

    function onContextMenu(ts, item, e){
        if(!menu){ // create context menu on first right click
            menu = new Ext.menu.Menu([{
                id: tabs.id + '-close',
                text: '关闭当前标签',
                iconCls : 'ok',
                handler : function(){
                    tabs.remove(ctxItem);
                }
            },{
                id: tabs.id + '-close-others',
                iconCls : 'delete',
                text: '关闭其它标签',
                handler : function(){
                    tabs.items.each(function(item){
                        if(item.closable && item != ctxItem){
                            tabs.remove(item);
                        }
                    });
                }
            }]);
        }
        ctxItem = item;
        var items = menu.items;
        items.get(tabs.id + '-close').setDisabled(!item.closable);
        var disableOthers = true;
        tabs.items.each(function(){
            if(this != item && this.closable){
                disableOthers = false;
                return false;
            }
        });
        items.get(tabs.id + '-close-others').setDisabled(disableOthers);
        menu.showAt(e.getPoint());
    }
};

// vim: ts=4:sw=4:nu:fdc=4:nospell
/**
 * Ext.ux.form.LovCombo, List of Values Combo
 *
 * @author    Ing. Jozef Sakáloš
 * @copyright (c) 2008, by Ing. Jozef Sakáloš
 * @date      16. April 2008
 * @version   $Id: Hxcy-cmp.js,v 1.39.2.17 2010/07/28 08:52:04 czk Exp $
 *
 * @license Ext.ux.form.LovCombo.js is licensed under the terms of the Open Source
 * LGPL 3.0 license. Commercial use is permitted to the extent that the 
 * code/component(s) do NOT become part of another Open Source or Commercially
 * licensed development library or toolkit without explicit permission.
 * 
 * License details: http://www.gnu.org/licenses/lgpl.html
 */
 
/*global Ext */

// add RegExp.escape if it has not been already added
if('function' !== typeof RegExp.escape) {
	RegExp.escape = function(s) {
		if('string' !== typeof s) {
			return s;
		}
		// Note: if pasting from forum, precede ]/\ with backslash manually
		return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
	}; // eo function escape
}

// create namespace
Ext.ns('Ext.ux.form');
 
/**
 *
 * @class Ext.ux.form.LovCombo
 * @extends Ext.form.ComboBox
 */
Ext.ux.form.LovCombo = Ext.extend(Ext.form.ComboBox, {

	// {{{
    // configuration options
	/**
	 * @cfg {String} checkField name of field used to store checked state.
	 * It is automatically added to existing fields.
	 * Change it only if it collides with your normal field.
	 */
	 checkField:'checked'

	/**
	 * @cfg {String} separator separator to use between values and texts
	 */
    ,separator:','

	/**
	 * @cfg {String/Array} tpl Template for items. 
	 * Change it only if you know what you are doing.
	 */
	// }}}
    // {{{
    ,initComponent:function() {
        
		// template with checkbox
		if(!this.tpl) {
			this.tpl = 
				 '<tpl for=".">'
				+'<div class="x-combo-list-item">'
				+'<img src="' + Ext.BLANK_IMAGE_URL + '" '
				+'class="ux-lovcombo-icon ux-lovcombo-icon-'
				+'{[values.' + this.checkField + '?"checked":"unchecked"' + ']}">'
				+'<div class="ux-lovcombo-item-text">{' + (this.displayField || 'text' )+ '}</div>'
				+'</div>'
				+'</tpl>'
			;
		}
 
        // call parent
        Ext.ux.form.LovCombo.superclass.initComponent.apply(this, arguments);

		// install internal event handlers
		this.on({
			 scope:this
			,beforequery:this.onBeforeQuery
			,blur:this.onRealBlur
		});

		// remove selection from input field
		this.onLoad = this.onLoad.createSequence(function() {
			if(this.el) {
				var v = this.el.dom.value;
				this.el.dom.value = '';
				this.el.dom.value = v;
			}
		});
 
    } // e/o function initComponent
    // }}}
	// {{{
	/**
	 * Disables default tab key bahavior
	 * @private
	 */
	,initEvents:function() {
		Ext.ux.form.LovCombo.superclass.initEvents.apply(this, arguments);

		// disable default tab handling - does no good
		this.keyNav.tab = false;

	} // eo function initEvents
	// }}}
	// {{{
	/**
	 * clears value
	 */
	,clearValue:function() {
		this.value = '';
		this.setRawValue(this.value);
		this.store.clearFilter();
		this.store.each(function(r) {
			r.set(this.checkField, false);
		}, this);
		if(this.hiddenField) {
			this.hiddenField.value = '';
		}
		this.applyEmptyText();
	} // eo function clearValue
	// }}}
	// {{{
	/**
	 * @return {String} separator (plus space) separated list of selected displayFields
	 * @private
	 */
	,getCheckedDisplay:function() {
		var re = new RegExp(this.separator, "g");
		return this.getCheckedValue(this.displayField).replace(re, this.separator + ' ');
	} // eo function getCheckedDisplay
	// }}}
	// {{{
	/**
	 * @return {String} separator separated list of selected valueFields
	 * @private
	 */
	,getCheckedValue:function(field) {
		field = field || this.valueField;
		var c = [];

		// store may be filtered so get all records
		var snapshot = this.store.snapshot || this.store.data;

		snapshot.each(function(r) {
			if(r.get(this.checkField)) {
				c.push(r.get(field));
			}
		}, this);

		return c.join(this.separator);
	} // eo function getCheckedValue
	// }}}
	// {{{
	/**
	 * beforequery event handler - handles multiple selections
	 * @param {Object} qe query event
	 * @private
	 */
	,onBeforeQuery:function(qe) {
		qe.query = qe.query.replace(new RegExp(this.getCheckedDisplay() + '[ ' + this.separator + ']*'), '');
	} // eo function onBeforeQuery
	// }}}
	// {{{
	/**
	 * blur event handler - runs only when real blur event is fired
	 */
	,onRealBlur:function() {
		this.list.hide();
		var rv = this.getRawValue();
		var rva = rv.split(new RegExp(RegExp.escape(this.separator) + ' *'));
		var va = [];
		var snapshot = this.store.snapshot || this.store.data;

		// iterate through raw values and records and check/uncheck items
		Ext.each(rva, function(v) {
			snapshot.each(function(r) {
				if(v === r.get(this.displayField)) {
					va.push(r.get(this.valueField));
				}
			}, this);
		}, this);
		this.setValue(va.join(this.separator));
		this.store.clearFilter();
	} // eo function onRealBlur
	// }}}
	// {{{
	/**
	 * Combo's onSelect override
	 * @private
	 * @param {Ext.data.Record} record record that has been selected in the list
	 * @param {Number} index index of selected (clicked) record
	 */
	,onSelect:function(record, index) {
        if(this.fireEvent('beforeselect', this, record, index) !== false){

			// toggle checked field
			record.set(this.checkField, !record.get(this.checkField));

			// display full list
			if(this.store.isFiltered()) {
				this.doQuery(this.allQuery);
			}

			// set (update) value and fire event
			this.setValue(this.getCheckedValue());
            this.fireEvent('select', this, record, index);
        }
	} // eo function onSelect
	// }}}
	// {{{
	/**
	 * Sets the value of the LovCombo
	 * @param {Mixed} v value
	 */
	,setValue:function(v) {
		if(v) {
			v = '' + v;
			if(this.valueField) {
				this.store.clearFilter();
				this.store.each(function(r) {
					var checked = !(!v.match(
						 '(^|' + this.separator + ')' + RegExp.escape(r.get(this.valueField))
						+'(' + this.separator + '|$)'))
					;

					r.set(this.checkField, checked);
				}, this);
				this.value = this.getCheckedValue();
				this.setRawValue(this.getCheckedDisplay());
				if(this.hiddenField) {
					this.hiddenField.value = this.value;
				}
			}
			else {
				this.value = v;
				this.setRawValue(v);
				if(this.hiddenField) {
					this.hiddenField.value = v;
				}
			}
			if(this.el) {
				this.el.removeClass(this.emptyClass);
			}
		}
		else {
			this.clearValue();
		}
	} // eo function setValue
	// }}}
	// {{{
	/**
	 * Selects all items
	 */
	,selectAll:function() {
        this.store.each(function(record){
            // toggle checked field
            record.set(this.checkField, true);
        }, this);

        //display full list
        this.doQuery(this.allQuery);
        this.setValue(this.getCheckedValue());
    } // eo full selectAll
	// }}}
	// {{{
	/**
	 * Deselects all items. Synonym for clearValue
	 */
    ,deselectAll:function() {
		this.clearValue();
    } // eo full deselectAll 
	// }}}

}); // eo extend
 
// register xtype
Ext.reg('lovcombo', Ext.ux.form.LovCombo); 

// eof
Ext.ux.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
	monitorResize : true,
	setContainer : function() {
		Ext.layout.FormLayout.prototype.setContainer.apply(this, arguments);
		Ext.ux.TableFormLayout.prototype.fieldTpl = Ext.layout.FormLayout.prototype.fieldTpl;
		Ext.ux.TableFormLayout.superclass.setContainer.apply(this, arguments);
	},
	renderItem : function(c, position, target) {
		if (c && !c.rendered) {
			Ext.layout.FormLayout.prototype.renderItem.call(this, c, 0, Ext
					.get(this.getNextCell(c)));
		}
	},
	getAnchorSize : function(ct) {
		var aw, ah;
		if (ct.anchorSize) {
			if (typeof ct.anchorSize == "number") {
				aw = ct.anchorSize;
			} else {
				aw = ct.anchorSize.width;
				ah = ct.anchorSize.height;
			}
		} else {
			aw = ct.initialConfig.width;
			ah = ct.initialConfig.height;
		}
		return [aw, ah];
	},
	getAnchorViewSize : function(ct, target) {
		return Ext.fly(ct.body).getStyleSize();
	},
	getCellWH : function(c, viewSize, i) {
		var cell, w, h, cell = c.getEl().parent(".x-table-layout-cell");
		//alert(viewSize.width);
		w = (viewSize.width / this.columns) * (c.colspan || 1);
		if(this.onWH){
		  w=this.onWH(c,cell,viewSize.width , this.columns,c.colspan || 1,w);
		}
		//alert(w);
		cell.setWidth(w+10);
		// w = w - 10;
		h = cell.getHeight();
		//cell.setHeight(h);
		if (this.onCellWH)
			return this.onCellWH(c, cell, viewSize, i, w, h);
		return [w, h];
	},
	calAnchorSpec : function(c, a) {
		var cw = c.initialConfig.width, ch = c.initialConfig.height;
		if (!c.anchorSpec) {
			var vs = c.anchor.split(" ");
			c.anchorSpec = {
				right : this.parseAnchor(vs[0], cw, a[0]),
				bottom : this.parseAnchor(vs[1], ch, a[1])
			};
		}
		return c.anchorSpec;
	},
	  adjustHeightAnchor : function(value, comp){
	  //	alert(value);
        return value;
    }    ,
     adjustWidthAnchor : function(value, comp){
     //	alert(value);
        return value - (comp.isFormField  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
    },
	calSize : function(c, wh, a) {
		var cw = a.right
				? this.adjustWidthAnchor(a.right(wh[0]), c)
				: undefined;
		var ch = a.bottom
				? this.adjustHeightAnchor(a.bottom(wh[1]), c)
				: undefined;
				//alert('cwh'+cw+":"+ch);
		if (cw || ch) {
			c.setSize(cw || undefined, ch || undefined);
		}
	},
	onLayout : function(ct, target) {
		Ext.ux.TableFormLayout.superclass.onLayout.call(this, ct, target);
		if (!target.hasClass("x-table-form-layout-ct")) {
			target.addClass("x-table-form-layout-ct");
		}
		var viewSize = this.getAnchorViewSize(ct, target);
		var anchorSize = this.getAnchorSize(ct);
		var cs = ct.items.items, len = cs.length, i, c, wh, anchorSpec;
		for (i = 0; i < len; i++) {
			c = cs[i];
			wh = this.getCellWH(c, viewSize, i);
			if (c.anchor) {
				anchorSpec = this.calAnchorSpec(c, anchorSize);
				this.calSize(c, wh, anchorSpec);
			}
		}
	}
});
Ext.applyIf(Ext.ux.TableFormLayout.prototype, Ext.layout.FormLayout.prototype);
Ext.Container.LAYOUTS["tableform"] = Ext.ux.TableFormLayout;

/*Hxcy.TableFormLayout = Ext.extend(Ext.layout.TableLayout, {
	monitorResize : false,
	labelSeparator : ':',
	
	subContainerDefault : {
		layoutConfig: {
			tableAttrs : {align:'center', width:'100%', style:'table-layout : fixed;'},
			columns: 2
		}
	},
	
	onLayout : function(ct, target){
		Hxcy.TableFormLayout.superclass.onLayout.call(this, ct, target);
		var items = ct.items;
		items.each(function(item){
			var td = item.el.parent('td.x-table-layout-cell');
			alert(td.getWidth(true)+'TTT'+td.getHeight(true));
			if(item.fit===true){
				item.setSize(td.getWidth(true), td.getHeight(true));
			}
		});
	},
	
	setContainer : function(ct){
		Hxcy.TableFormLayout.superclass.setContainer.call(this, ct);
		if(ct.labelAlign){
			ct.addClass('x-form-label-'+ct.labelAlign);
		}
		
		if(ct.hideLabels){
			this.labelStyle ="display:none";
			this.elementStyle ="padding-left:0;";
			this.labelAdjust = 0;
		}else{
			this.labelSeparator = ct.labelSeparator || this.labelSeparator;
			ct.labelWidth = ct.labelWidth || 100;
			if(typeof ct.labelWidth == 'number'){
				var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
				this.labelAdjust = ct.labelWidth+pad;
				this.labelStyle ="width:"+ct.labelWidth+"px;";
				this.elementStyle ="padding-left:"+(ct.labelWidth+pad)+'px;';
			}
			if(ct.labelAlign == 'top'){
				this.labelStyle ="width:auto;";
				this.labelAdjust = 0;
				this.elementStyle = "padding-left:0;";
			}
		}
	},
	getNextCell : function(c){
		//获取下一个单元格的行列值
		var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
		var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
		for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
			if(!this.cells[rowIndex]){
				this.cells[rowIndex] = [];
			}
			for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
				this.cells[rowIndex][colIndex] = true;
			}
		}
		var tdAttr = c.tdAttr||this.tdAttr ||{};
		if(c.cellId){
			tdAttr.id = c.cellId;
		}
		var cls = 'x-table-layout-cell';
		if(c.cellCls){
			cls += ' ' + c.cellCls;
		}
		tdAttr.cls = cls;
		if(c.colspan){
			tdAttr.colSpan = c.colspan;
		}
		if(c.rowspan){
			tdAttr.rowSpan = c.rowspan;
		}
		tdAttr.tag='td';
		var td = Ext.DomHelper.append( this.getRow(curRow), tdAttr);
		return td;
	},
	renderItem : function(c, position, target){
		if(c && !c.rendered ){
			if(this.extraCls){
				var t = c.getPositionEl ? c.getPositionEl() : c;
				t.addClass(this.extraCls);
			}
			
			if (c.inTable!==false&&(c.isFormField || c.fieldLabel) && c.inputType != 'hidden') {
				//如果是一个表单域
				target = this.getNextCell(c);
				var args = this.getTemplateArgs(c);
				this.fieldTpl.append(target, args);
				//前面步骤主要是在包装一个表单域,下面是在一个包装中嵌入(渲染)真正的表单域
				//'x-form-el-'+c.id是在包装模板中指定的dom容器,对于表单的包装体主要需要了解两个类,x-form-item是对整个表单域的包装
				//包括表单标签在内;x-form-element是对表单域直接容器,即是表单元素的直接上级容器元素;x-form-item-label是表单标签类
				c.render('x-form-el-'+c.id);
			} else if (c.inTable===true) {//在这里进行这样的处理主要为了在表单中加,一些容器,容器
				Hxcy.Util.applyIf(c, this.subContainerDefault);
				target = this.getNextCell(c);
				c.render(target);
			} else {//在这里进行这样的处理主要为了在表单中加,一些容器,容器
				Hxcy.Util.applyIf(c, this.subContainerDefault);
				c.render(target);
			}
		}
	},
	getTemplateArgs: function(field) {
		var noLabelSep = !field.fieldLabel || field.hideLabel;
		return {
			id: field.id,
			label: field.fieldLabel,
			labelStyle: field.labelStyle||this.labelStyle||'',
			elementStyle: field.elementStyle||this.elementStyle||'',
			labelSeparator: noLabelSep ? '' : (typeof field.labelSeparator == 'undefined' ? this.labelSeparator : field.labelSeparator),
			itemCls: (field.itemCls||this.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
			clearCls: field.clearCls || 'x-form-clear-left'
		};
	}
});
Ext.Container.LAYOUTS['tableform'] = Hxcy.TableFormLayout;*/

/*Hxcy.ItemSelector = function(config) {
	Hxcy.ItemSelector.superclass.constructor.call(this, config);
};

Ext.extend(Hxcy.ItemSelector, Ext.Container, {
	initComponent : function(){
		var provider = this.provider;
		delete this.provider;
		var pvdRoot = this.pvdRoot || {};
		var pvdCheckModel = this.pvdCheckModel || {};
		var pvdStore = this.pvdStore || {};
			
		
		//这个方法在超类方法之前执行很重要
		Ext.applyIf(this, {
			layout : 'form',
			items : [provider]
		})
		Hxcy.ItemSelector.superclass.initComponent.call(this);
	},
	
	onRender : function(ct, position){
		Hxcy.ItemSelector.superclass.onRender.call(this, ct, position);
	}
});
Ext.reg('itemselector', Hxcy.ItemSelector);
*/